Outline & Path perf improvements

Bug: 33460152
Test: device boots, ViewShowHidePerfTests#add[Factory:NestedLinearLayoutTree,depth:6] 770us -> 650us (userdebug 960MHz bullhead)

Improve perf for outline & simple path methods

native_methodName -> nMethodName in Path.java

Change-Id: Id2374bbaca3256d2e4f19dae9abe67f794a171b3
diff --git a/apct-tests/perftests/core/src/android/graphics/perftests/PathPerfTest.java b/apct-tests/perftests/core/src/android/graphics/perftests/PathPerfTest.java
new file mode 100644
index 0000000..7a49b4f
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/graphics/perftests/PathPerfTest.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2016 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
+ *
+ *      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
+ * limitations under the License.
+ */
+
+package android.graphics.perftests;
+
+import android.graphics.Path;
+import android.graphics.RectF;
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.support.test.filters.LargeTest;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+@LargeTest
+public class PathPerfTest {
+    @Rule
+    public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Test
+    public void testReset() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        Path path = new Path();
+        while (state.keepRunning()) {
+            path.reset();
+        }
+    }
+
+    @Test
+    public void testAddReset() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        Path path = new Path();
+        while (state.keepRunning()) {
+            path.addRect(0, 0, 100, 100, Path.Direction.CW);
+            path.reset();
+        }
+    }
+
+    @Test
+    public void testRewind() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        Path path = new Path();
+        while (state.keepRunning()) {
+            path.rewind();
+        }
+    }
+
+    @Test
+    public void testAddRewind() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        Path path = new Path();
+        while (state.keepRunning()) {
+            path.addRect(0, 0, 100, 100, Path.Direction.CW);
+            path.rewind();
+        }
+    }
+
+    @Test
+    public void testIsEmpty() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        Path path = new Path();
+        path.addRect(0, 0, 100, 100, Path.Direction.CW);
+        while (state.keepRunning()) {
+            path.isEmpty();
+        }
+    }
+
+    @Test
+    public void testIsConvex() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        Path path = new Path();
+        path.addRect(0, 0, 100, 100, Path.Direction.CW);
+        while (state.keepRunning()) {
+            path.isConvex();
+        }
+    }
+
+    @Test
+    public void testGetSetFillType() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        Path path = new Path();
+        path.addRect(0, 0, 100, 100, Path.Direction.CW);
+        while (state.keepRunning()) {
+            path.setFillType(Path.FillType.EVEN_ODD);
+            path.getFillType();
+        }
+    }
+
+    @Test
+    public void testIsRect() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        Path path = new Path();
+        path.addRect(0, 0, 100, 100, Path.Direction.CW);
+        final RectF outRect = new RectF();
+        while (state.keepRunning()) {
+            path.isRect(outRect);
+        }
+    }
+}
diff --git a/core/jni/android/graphics/Path.cpp b/core/jni/android/graphics/Path.cpp
index ab393f2..292454b 100644
--- a/core/jni/android/graphics/Path.cpp
+++ b/core/jni/android/graphics/Path.cpp
@@ -36,7 +36,18 @@
 class SkPathGlue {
 public:
 
-    static void finalizer(JNIEnv* env, jobject clazz, jlong objHandle) {
+    // ---------------- Regular JNI -----------------------------
+
+    static jlong init(JNIEnv* env, jclass clazz) {
+        return reinterpret_cast<jlong>(new SkPath());
+    }
+
+    static jlong init_Path(JNIEnv* env, jclass clazz, jlong valHandle) {
+        SkPath* val = reinterpret_cast<SkPath*>(valHandle);
+        return reinterpret_cast<jlong>(new SkPath(*val));
+    }
+
+    static void finalize(JNIEnv* env, jclass clazz, jlong objHandle) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         // Purge entries from the HWUI path cache if this path's data is unique
         if (obj->unique() && android::uirenderer::Caches::hasInstance()) {
@@ -45,112 +56,68 @@
         delete obj;
     }
 
-    static jlong init1(JNIEnv* env, jobject clazz) {
-        return reinterpret_cast<jlong>(new SkPath());
-    }
-
-    static jlong init2(JNIEnv* env, jobject clazz, jlong valHandle) {
-        SkPath* val = reinterpret_cast<SkPath*>(valHandle);
-        return reinterpret_cast<jlong>(new SkPath(*val));
-    }
-
-    static void reset(JNIEnv* env, jobject clazz, jlong objHandle) {
-        SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
-        obj->reset();
-    }
-
-    static void rewind(JNIEnv* env, jobject clazz, jlong objHandle) {
-        SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
-        obj->rewind();
-    }
-
-    static void assign(JNIEnv* env, jobject clazz, jlong dstHandle, jlong srcHandle) {
+    static void set(JNIEnv* env, jclass clazz, jlong dstHandle, jlong srcHandle) {
         SkPath* dst = reinterpret_cast<SkPath*>(dstHandle);
         const SkPath* src = reinterpret_cast<SkPath*>(srcHandle);
         *dst = *src;
     }
 
-    static jboolean isConvex(JNIEnv* env, jobject clazz, jlong objHandle) {
-        SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
-        return obj->isConvex();
-    }
-
-    static jint getFillType(JNIEnv* env, jobject clazz, jlong objHandle) {
-        SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
-        return obj->getFillType();
-    }
-
-    static void setFillType(JNIEnv* env, jobject clazz, jlong pathHandle, jint ftHandle) {
-        SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
-        SkPath::FillType ft = static_cast<SkPath::FillType>(ftHandle);
-        path->setFillType(ft);
-    }
-
-    static jboolean isEmpty(JNIEnv* env, jobject clazz, jlong objHandle) {
-        SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
-        return obj->isEmpty();
-    }
-
-    static jboolean isRect(JNIEnv* env, jobject clazz, jlong objHandle, jobject jrect) {
-        SkRect rect;
-        SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
-        jboolean result = obj->isRect(&rect);
-        GraphicsJNI::rect_to_jrectf(rect, env, jrect);
-        return result;
-    }
-
-    static void computeBounds(JNIEnv* env, jobject clazz, jlong objHandle, jobject jbounds) {
+    static void computeBounds(JNIEnv* env, jclass clazz, jlong objHandle, jobject jbounds) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         const SkRect& bounds = obj->getBounds();
         GraphicsJNI::rect_to_jrectf(bounds, env, jbounds);
     }
 
-    static void incReserve(JNIEnv* env, jobject clazz, jlong objHandle, jint extraPtCount) {
+    static void incReserve(JNIEnv* env, jclass clazz, jlong objHandle, jint extraPtCount) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         obj->incReserve(extraPtCount);
     }
 
-    static void moveTo__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x, jfloat y) {
+    static void moveTo__FF(JNIEnv* env, jclass clazz, jlong objHandle, jfloat x, jfloat y) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         obj->moveTo(x, y);
     }
 
-    static void rMoveTo(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy) {
+    static void rMoveTo(JNIEnv* env, jclass clazz, jlong objHandle, jfloat dx, jfloat dy) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         obj->rMoveTo(dx, dy);
     }
 
-    static void lineTo__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x, jfloat y) {
+    static void lineTo__FF(JNIEnv* env, jclass clazz, jlong objHandle, jfloat x, jfloat y) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         obj->lineTo(x, y);
     }
 
-    static void rLineTo(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy) {
+    static void rLineTo(JNIEnv* env, jclass clazz, jlong objHandle, jfloat dx, jfloat dy) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         obj->rLineTo(dx, dy);
     }
 
-    static void quadTo__FFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x1, jfloat y1, jfloat x2, jfloat y2) {
+    static void quadTo__FFFF(JNIEnv* env, jclass clazz, jlong objHandle, jfloat x1, jfloat y1,
+            jfloat x2, jfloat y2) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         obj->quadTo(x1, y1, x2, y2);
     }
 
-    static void rQuadTo(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx1, jfloat dy1, jfloat dx2, jfloat dy2) {
+    static void rQuadTo(JNIEnv* env, jclass clazz, jlong objHandle, jfloat dx1, jfloat dy1,
+            jfloat dx2, jfloat dy2) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         obj->rQuadTo(dx1, dy1, dx2, dy2);
     }
 
-    static void cubicTo__FFFFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x1, jfloat y1, jfloat x2, jfloat y2, jfloat x3, jfloat y3) {
+    static void cubicTo__FFFFFF(JNIEnv* env, jclass clazz, jlong objHandle, jfloat x1, jfloat y1,
+            jfloat x2, jfloat y2, jfloat x3, jfloat y3) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         obj->cubicTo(x1, y1, x2, y2, x3, y3);
     }
 
-    static void rCubicTo(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x1, jfloat y1, jfloat x2, jfloat y2, jfloat x3, jfloat y3) {
+    static void rCubicTo(JNIEnv* env, jclass clazz, jlong objHandle, jfloat x1, jfloat y1,
+            jfloat x2, jfloat y2, jfloat x3, jfloat y3) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         obj->rCubicTo(x1, y1, x2, y2, x3, y3);
     }
 
-    static void arcTo(JNIEnv* env, jobject clazz, jlong objHandle, jfloat left, jfloat top,
+    static void arcTo(JNIEnv* env, jclass clazz, jlong objHandle, jfloat left, jfloat top,
             jfloat right, jfloat bottom, jfloat startAngle, jfloat sweepAngle,
             jboolean forceMoveTo) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
@@ -158,19 +125,19 @@
         obj->arcTo(oval, startAngle, sweepAngle, forceMoveTo);
     }
 
-    static void close(JNIEnv* env, jobject clazz, jlong objHandle) {
+    static void close(JNIEnv* env, jclass clazz, jlong objHandle) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         obj->close();
     }
 
-    static void addRect(JNIEnv* env, jobject clazz, jlong objHandle,
+    static void addRect(JNIEnv* env, jclass clazz, jlong objHandle,
             jfloat left, jfloat top, jfloat right, jfloat bottom, jint dirHandle) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         SkPath::Direction dir = static_cast<SkPath::Direction>(dirHandle);
         obj->addRect(left, top, right, bottom, dir);
     }
 
-    static void addOval(JNIEnv* env, jobject clazz, jlong objHandle,
+    static void addOval(JNIEnv* env, jclass clazz, jlong objHandle,
             jfloat left, jfloat top, jfloat right, jfloat bottom, jint dirHandle) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         SkPath::Direction dir = static_cast<SkPath::Direction>(dirHandle);
@@ -178,20 +145,21 @@
         obj->addOval(oval, dir);
     }
 
-    static void addCircle(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x, jfloat y, jfloat radius, jint dirHandle) {
+    static void addCircle(JNIEnv* env, jclass clazz, jlong objHandle, jfloat x, jfloat y,
+            jfloat radius, jint dirHandle) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         SkPath::Direction dir = static_cast<SkPath::Direction>(dirHandle);
         obj->addCircle(x, y, radius, dir);
     }
 
-    static void addArc(JNIEnv* env, jobject clazz, jlong objHandle, jfloat left, jfloat top,
+    static void addArc(JNIEnv* env, jclass clazz, jlong objHandle, jfloat left, jfloat top,
             jfloat right, jfloat bottom, jfloat startAngle, jfloat sweepAngle) {
         SkRect oval = SkRect::MakeLTRB(left, top, right, bottom);
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         obj->addArc(oval, startAngle, sweepAngle);
     }
 
-    static void addRoundRectXY(JNIEnv* env, jobject clazz, jlong objHandle, jfloat left, jfloat top,
+    static void addRoundRectXY(JNIEnv* env, jclass clazz, jlong objHandle, jfloat left, jfloat top,
             jfloat right, jfloat bottom, jfloat rx, jfloat ry, jint dirHandle) {
         SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
@@ -199,8 +167,8 @@
         obj->addRoundRect(rect, rx, ry, dir);
     }
 
-    static void addRoundRect8(JNIEnv* env, jobject, jlong objHandle, jfloat left, jfloat top,
-            jfloat right, jfloat bottom, jfloatArray array, jint dirHandle) {
+    static void addRoundRect8(JNIEnv* env, jclass clazz, jlong objHandle, jfloat left, jfloat top,
+                jfloat right, jfloat bottom, jfloatArray array, jint dirHandle) {
         SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         SkPath::Direction dir = static_cast<SkPath::Direction>(dirHandle);
@@ -213,49 +181,53 @@
         obj->addRoundRect(rect, src, dir);
     }
 
-    static void addPath__PathFF(JNIEnv* env, jobject clazz, jlong objHandle, jlong srcHandle, jfloat dx, jfloat dy) {
+    static void addPath__PathFF(JNIEnv* env, jclass clazz, jlong objHandle, jlong srcHandle,
+            jfloat dx, jfloat dy) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         SkPath* src = reinterpret_cast<SkPath*>(srcHandle);
         obj->addPath(*src, dx, dy);
     }
 
-    static void addPath__Path(JNIEnv* env, jobject clazz, jlong objHandle, jlong srcHandle) {
+    static void addPath__Path(JNIEnv* env, jclass clazz, jlong objHandle, jlong srcHandle) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         SkPath* src = reinterpret_cast<SkPath*>(srcHandle);
         obj->addPath(*src);
     }
 
-    static void addPath__PathMatrix(JNIEnv* env, jobject clazz, jlong objHandle, jlong srcHandle, jlong matrixHandle) {
+    static void addPath__PathMatrix(JNIEnv* env, jclass clazz, jlong objHandle, jlong srcHandle,
+            jlong matrixHandle) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         SkPath* src = reinterpret_cast<SkPath*>(srcHandle);
         SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
         obj->addPath(*src, *matrix);
     }
 
-    static void offset__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy) {
+    static void offset__FF(JNIEnv* env, jclass clazz, jlong objHandle, jfloat dx, jfloat dy) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         obj->offset(dx, dy);
     }
 
-    static void setLastPoint(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy) {
+    static void setLastPoint(JNIEnv* env, jclass clazz, jlong objHandle, jfloat dx, jfloat dy) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         obj->setLastPt(dx, dy);
     }
 
-    static void transform__MatrixPath(JNIEnv* env, jobject clazz, jlong objHandle, jlong matrixHandle, jlong dstHandle) {
+    static void transform__MatrixPath(JNIEnv* env, jclass clazz, jlong objHandle, jlong matrixHandle,
+            jlong dstHandle) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
         SkPath* dst = reinterpret_cast<SkPath*>(dstHandle);
         obj->transform(*matrix, dst);
     }
 
-    static void transform__Matrix(JNIEnv* env, jobject clazz, jlong objHandle, jlong matrixHandle) {
+    static void transform__Matrix(JNIEnv* env, jclass clazz, jlong objHandle, jlong matrixHandle) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
         obj->transform(*matrix);
     }
 
-    static jboolean op(JNIEnv* env, jobject clazz, jlong p1Handle, jlong p2Handle, jint opHandle, jlong rHandle) {
+    static jboolean op(JNIEnv* env, jclass clazz, jlong p1Handle, jlong p2Handle, jint opHandle,
+            jlong rHandle) {
         SkPath* p1  = reinterpret_cast<SkPath*>(p1Handle);
         SkPath* p2  = reinterpret_cast<SkPath*>(p2Handle);
         SkPathOp op = static_cast<SkPathOp>(opHandle);
@@ -416,8 +388,8 @@
     // Note that more than one point may have the same length along the path in
     // the case of a move.
     // NULL can be returned if the Path is empty.
-    static jfloatArray approximate(JNIEnv* env, jclass, jlong pathHandle, float acceptableError)
-    {
+    static jfloatArray approximate(JNIEnv* env, jclass clazz, jlong pathHandle,
+            float acceptableError) {
         SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
         SkASSERT(path);
         SkPath::Iter pathIter(*path, false);
@@ -467,47 +439,94 @@
         delete[] approximation;
         return result;
     }
+
+    // ---------------- @FastNative -----------------------------
+
+    static jboolean isRect(JNIEnv* env, jclass clazz, jlong objHandle, jobject jrect) {
+        SkRect rect;
+        SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
+        jboolean result = obj->isRect(&rect);
+        GraphicsJNI::rect_to_jrectf(rect, env, jrect);
+        return result;
+    }
+
+    // ---------------- @CriticalNative -------------------------
+
+    static void reset(jlong objHandle) {
+        SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
+        obj->reset();
+    }
+
+    static void rewind(jlong objHandle) {
+        SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
+        obj->rewind();
+    }
+
+    static jboolean isEmpty(jlong objHandle) {
+        SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
+        return obj->isEmpty();
+    }
+
+    static jboolean isConvex(jlong objHandle) {
+        SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
+        return obj->isConvex();
+    }
+
+    static jint getFillType(jlong objHandle) {
+        SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
+        return obj->getFillType();
+    }
+
+    static void setFillType(jlong pathHandle, jint ftHandle) {;
+        SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
+        SkPath::FillType ft = static_cast<SkPath::FillType>(ftHandle);
+        path->setFillType(ft);
+    }
 };
 
 static const JNINativeMethod methods[] = {
-    {"finalizer", "(J)V", (void*) SkPathGlue::finalizer},
-    {"init1","()J", (void*) SkPathGlue::init1},
-    {"init2","(J)J", (void*) SkPathGlue::init2},
-    {"native_reset","(J)V", (void*) SkPathGlue::reset},
-    {"native_rewind","(J)V", (void*) SkPathGlue::rewind},
-    {"native_set","(JJ)V", (void*) SkPathGlue::assign},
-    {"native_isConvex","(J)Z", (void*) SkPathGlue::isConvex},
-    {"native_getFillType","(J)I", (void*) SkPathGlue::getFillType},
-    {"native_setFillType","(JI)V", (void*) SkPathGlue::setFillType},
-    {"native_isEmpty","(J)Z", (void*) SkPathGlue::isEmpty},
-    {"native_isRect","(JLandroid/graphics/RectF;)Z", (void*) SkPathGlue::isRect},
-    {"native_computeBounds","(JLandroid/graphics/RectF;)V", (void*) SkPathGlue::computeBounds},
-    {"native_incReserve","(JI)V", (void*) SkPathGlue::incReserve},
-    {"native_moveTo","(JFF)V", (void*) SkPathGlue::moveTo__FF},
-    {"native_rMoveTo","(JFF)V", (void*) SkPathGlue::rMoveTo},
-    {"native_lineTo","(JFF)V", (void*) SkPathGlue::lineTo__FF},
-    {"native_rLineTo","(JFF)V", (void*) SkPathGlue::rLineTo},
-    {"native_quadTo","(JFFFF)V", (void*) SkPathGlue::quadTo__FFFF},
-    {"native_rQuadTo","(JFFFF)V", (void*) SkPathGlue::rQuadTo},
-    {"native_cubicTo","(JFFFFFF)V", (void*) SkPathGlue::cubicTo__FFFFFF},
-    {"native_rCubicTo","(JFFFFFF)V", (void*) SkPathGlue::rCubicTo},
-    {"native_arcTo","(JFFFFFFZ)V", (void*) SkPathGlue::arcTo},
-    {"native_close","(J)V", (void*) SkPathGlue::close},
-    {"native_addRect","(JFFFFI)V", (void*) SkPathGlue::addRect},
-    {"native_addOval","(JFFFFI)V", (void*) SkPathGlue::addOval},
-    {"native_addCircle","(JFFFI)V", (void*) SkPathGlue::addCircle},
-    {"native_addArc","(JFFFFFF)V", (void*) SkPathGlue::addArc},
-    {"native_addRoundRect","(JFFFFFFI)V", (void*) SkPathGlue::addRoundRectXY},
-    {"native_addRoundRect","(JFFFF[FI)V", (void*) SkPathGlue::addRoundRect8},
-    {"native_addPath","(JJFF)V", (void*) SkPathGlue::addPath__PathFF},
-    {"native_addPath","(JJ)V", (void*) SkPathGlue::addPath__Path},
-    {"native_addPath","(JJJ)V", (void*) SkPathGlue::addPath__PathMatrix},
-    {"native_offset","(JFF)V", (void*) SkPathGlue::offset__FF},
-    {"native_setLastPoint","(JFF)V", (void*) SkPathGlue::setLastPoint},
-    {"native_transform","(JJJ)V", (void*) SkPathGlue::transform__MatrixPath},
-    {"native_transform","(JJ)V", (void*) SkPathGlue::transform__Matrix},
-    {"native_op","(JJIJ)Z", (void*) SkPathGlue::op},
-    {"native_approximate", "(JF)[F", (void*) SkPathGlue::approximate},
+    {"nInit","()J", (void*) SkPathGlue::init},
+    {"nInit","(J)J", (void*) SkPathGlue::init_Path},
+    {"nFinalize", "(J)V", (void*) SkPathGlue::finalize},
+    {"nSet","(JJ)V", (void*) SkPathGlue::set},
+    {"nComputeBounds","(JLandroid/graphics/RectF;)V", (void*) SkPathGlue::computeBounds},
+    {"nIncReserve","(JI)V", (void*) SkPathGlue::incReserve},
+    {"nMoveTo","(JFF)V", (void*) SkPathGlue::moveTo__FF},
+    {"nRMoveTo","(JFF)V", (void*) SkPathGlue::rMoveTo},
+    {"nLineTo","(JFF)V", (void*) SkPathGlue::lineTo__FF},
+    {"nRLineTo","(JFF)V", (void*) SkPathGlue::rLineTo},
+    {"nQuadTo","(JFFFF)V", (void*) SkPathGlue::quadTo__FFFF},
+    {"nRQuadTo","(JFFFF)V", (void*) SkPathGlue::rQuadTo},
+    {"nCubicTo","(JFFFFFF)V", (void*) SkPathGlue::cubicTo__FFFFFF},
+    {"nRCubicTo","(JFFFFFF)V", (void*) SkPathGlue::rCubicTo},
+    {"nArcTo","(JFFFFFFZ)V", (void*) SkPathGlue::arcTo},
+    {"nClose","(J)V", (void*) SkPathGlue::close},
+    {"nAddRect","(JFFFFI)V", (void*) SkPathGlue::addRect},
+    {"nAddOval","(JFFFFI)V", (void*) SkPathGlue::addOval},
+    {"nAddCircle","(JFFFI)V", (void*) SkPathGlue::addCircle},
+    {"nAddArc","(JFFFFFF)V", (void*) SkPathGlue::addArc},
+    {"nAddRoundRect","(JFFFFFFI)V", (void*) SkPathGlue::addRoundRectXY},
+    {"nAddRoundRect","(JFFFF[FI)V", (void*) SkPathGlue::addRoundRect8},
+    {"nAddPath","(JJFF)V", (void*) SkPathGlue::addPath__PathFF},
+    {"nAddPath","(JJ)V", (void*) SkPathGlue::addPath__Path},
+    {"nAddPath","(JJJ)V", (void*) SkPathGlue::addPath__PathMatrix},
+    {"nOffset","(JFF)V", (void*) SkPathGlue::offset__FF},
+    {"nSetLastPoint","(JFF)V", (void*) SkPathGlue::setLastPoint},
+    {"nTransform","(JJJ)V", (void*) SkPathGlue::transform__MatrixPath},
+    {"nTransform","(JJ)V", (void*) SkPathGlue::transform__Matrix},
+    {"nOp","(JJIJ)Z", (void*) SkPathGlue::op},
+    {"nApproximate", "(JF)[F", (void*) SkPathGlue::approximate},
+
+    // ------- @FastNative below here ----------------------
+    {"nIsRect","(JLandroid/graphics/RectF;)Z", (void*) SkPathGlue::isRect},
+
+    // ------- @CriticalNative below here ------------------
+    {"nReset","(J)V", (void*) SkPathGlue::reset},
+    {"nRewind","(J)V", (void*) SkPathGlue::rewind},
+    {"nIsEmpty","(J)Z", (void*) SkPathGlue::isEmpty},
+    {"nIsConvex","(J)Z", (void*) SkPathGlue::isConvex},
+    {"nGetFillType","(J)I", (void*) SkPathGlue::getFillType},
+    {"nSetFillType","(JI)V", (void*) SkPathGlue::setFillType},
 };
 
 int register_android_graphics_Path(JNIEnv* env) {
diff --git a/graphics/java/android/graphics/Outline.java b/graphics/java/android/graphics/Outline.java
index aa81b91..3e59f34 100644
--- a/graphics/java/android/graphics/Outline.java
+++ b/graphics/java/android/graphics/Outline.java
@@ -58,8 +58,12 @@
     @Mode
     public int mMode = MODE_EMPTY;
 
-    /** @hide */
-    public final Path mPath = new Path();
+    /**
+     * Only guaranteed to be non-null when mode == MODE_CONVEX_PATH
+     *
+     * @hide
+     */
+    public Path mPath;
 
     /** @hide */
     public final Rect mRect = new Rect();
@@ -87,8 +91,11 @@
      * @see #isEmpty()
      */
     public void setEmpty() {
+        if (mPath != null) {
+            // rewind here to avoid thrashing the allocations, but could alternately clear ref
+            mPath.rewind();
+        }
         mMode = MODE_EMPTY;
-        mPath.rewind();
         mRect.setEmpty();
         mRadius = RADIUS_UNDEFINED;
     }
@@ -148,7 +155,12 @@
      */
     public void set(@NonNull Outline src) {
         mMode = src.mMode;
-        mPath.set(src.mPath);
+        if (src.mMode == MODE_CONVEX_PATH) {
+            if (mPath == null) {
+                mPath = new Path();
+            }
+            mPath.set(src.mPath);
+        }
         mRect.set(src.mRect);
         mRadius = src.mRadius;
         mAlpha = src.mAlpha;
@@ -180,10 +192,13 @@
             return;
         }
 
+        if (mMode == MODE_CONVEX_PATH) {
+            // rewind here to avoid thrashing the allocations, but could alternately clear ref
+            mPath.rewind();
+        }
         mMode = MODE_ROUND_RECT;
         mRect.set(left, top, right, bottom);
         mRadius = radius;
-        mPath.rewind();
     }
 
     /**
@@ -236,8 +251,13 @@
             return;
         }
 
+        if (mPath == null) {
+            mPath = new Path();
+        } else {
+            mPath.rewind();
+        }
+
         mMode = MODE_CONVEX_PATH;
-        mPath.rewind();
         mPath.addOval(left, top, right, bottom, Path.Direction.CW);
         mRect.setEmpty();
         mRadius = RADIUS_UNDEFINED;
@@ -264,6 +284,10 @@
             throw new IllegalArgumentException("path must be convex");
         }
 
+        if (mPath == null) {
+            mPath = new Path();
+        }
+
         mMode = MODE_CONVEX_PATH;
         mPath.set(convexPath);
         mRect.setEmpty();
diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java
index 4ed2581..3631373 100644
--- a/graphics/java/android/graphics/Path.java
+++ b/graphics/java/android/graphics/Path.java
@@ -19,6 +19,9 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 
+import dalvik.annotation.optimization.CriticalNative;
+import dalvik.annotation.optimization.FastNative;
+
 /**
  * The Path class encapsulates compound (multiple contour) geometric paths
  * consisting of straight line segments, quadratic curves, and cubic curves.
@@ -46,7 +49,7 @@
      * Create an empty path
      */
     public Path() {
-        mNativePath = init1();
+        mNativePath = nInit();
     }
 
     /**
@@ -63,7 +66,7 @@
                 rects = new Region(src.rects);
             }
         }
-        mNativePath = init2(valNative);
+        mNativePath = nInit(valNative);
     }
 
     /**
@@ -77,7 +80,7 @@
         // We promised not to change this, so preserve it around the native
         // call, which does now reset fill type.
         final FillType fillType = getFillType();
-        native_reset(mNativePath);
+        nReset(mNativePath);
         setFillType(fillType);
     }
 
@@ -89,7 +92,7 @@
         isSimplePath = true;
         mLastDirection = null;
         if (rects != null) rects.setEmpty();
-        native_rewind(mNativePath);
+        nRewind(mNativePath);
     }
 
     /** Replace the contents of this with the contents of src.
@@ -99,7 +102,7 @@
             return;
         }
         isSimplePath = src.isSimplePath;
-        native_set(mNativePath, src.mNativePath);
+        nSet(mNativePath, src.mNativePath);
         if (!isSimplePath) {
             return;
         }
@@ -174,7 +177,7 @@
      * @see #op(Path, android.graphics.Path.Op)
      */
     public boolean op(Path path1, Path path2, Op op) {
-        if (native_op(path1.mNativePath, path2.mNativePath, op.ordinal(), this.mNativePath)) {
+        if (nOp(path1.mNativePath, path2.mNativePath, op.ordinal(), this.mNativePath)) {
             isSimplePath = false;
             rects = null;
             return true;
@@ -194,7 +197,7 @@
      * @return True if the path is convex.
      */
     public boolean isConvex() {
-        return native_isConvex(mNativePath);
+        return nIsConvex(mNativePath);
     }
 
     /**
@@ -243,7 +246,7 @@
      * @return the path's fill type
      */
     public FillType getFillType() {
-        return sFillTypeArray[native_getFillType(mNativePath)];
+        return sFillTypeArray[nGetFillType(mNativePath)];
     }
 
     /**
@@ -252,7 +255,7 @@
      * @param ft The new fill type for this path
      */
     public void setFillType(FillType ft) {
-        native_setFillType(mNativePath, ft.nativeInt);
+        nSetFillType(mNativePath, ft.nativeInt);
     }
 
     /**
@@ -261,7 +264,7 @@
      * @return true if the filltype is one of the INVERSE variants
      */
     public boolean isInverseFillType() {
-        final int ft = native_getFillType(mNativePath);
+        final int ft = nGetFillType(mNativePath);
         return (ft & FillType.INVERSE_WINDING.nativeInt) != 0;
     }
 
@@ -269,9 +272,9 @@
      * Toggles the INVERSE state of the filltype
      */
     public void toggleInverseFillType() {
-        int ft = native_getFillType(mNativePath);
+        int ft = nGetFillType(mNativePath);
         ft ^= FillType.INVERSE_WINDING.nativeInt;
-        native_setFillType(mNativePath, ft);
+        nSetFillType(mNativePath, ft);
     }
 
     /**
@@ -280,7 +283,7 @@
      * @return true if the path is empty (contains no lines or curves)
      */
     public boolean isEmpty() {
-        return native_isEmpty(mNativePath);
+        return nIsEmpty(mNativePath);
     }
 
     /**
@@ -293,7 +296,7 @@
      * @return     true if the path specifies a rectangle
      */
     public boolean isRect(RectF rect) {
-        return native_isRect(mNativePath, rect);
+        return nIsRect(mNativePath, rect);
     }
 
     /**
@@ -306,7 +309,7 @@
      */
     @SuppressWarnings({"UnusedDeclaration"})
     public void computeBounds(RectF bounds, boolean exact) {
-        native_computeBounds(mNativePath, bounds);
+        nComputeBounds(mNativePath, bounds);
     }
 
     /**
@@ -317,7 +320,7 @@
      *                     path
      */
     public void incReserve(int extraPtCount) {
-        native_incReserve(mNativePath, extraPtCount);
+        nIncReserve(mNativePath, extraPtCount);
     }
 
     /**
@@ -327,7 +330,7 @@
      * @param y The y-coordinate of the start of a new contour
      */
     public void moveTo(float x, float y) {
-        native_moveTo(mNativePath, x, y);
+        nMoveTo(mNativePath, x, y);
     }
 
     /**
@@ -341,7 +344,7 @@
      *           previous contour, to specify the start of a new contour
      */
     public void rMoveTo(float dx, float dy) {
-        native_rMoveTo(mNativePath, dx, dy);
+        nRMoveTo(mNativePath, dx, dy);
     }
 
     /**
@@ -354,7 +357,7 @@
      */
     public void lineTo(float x, float y) {
         isSimplePath = false;
-        native_lineTo(mNativePath, x, y);
+        nLineTo(mNativePath, x, y);
     }
 
     /**
@@ -369,7 +372,7 @@
      */
     public void rLineTo(float dx, float dy) {
         isSimplePath = false;
-        native_rLineTo(mNativePath, dx, dy);
+        nRLineTo(mNativePath, dx, dy);
     }
 
     /**
@@ -384,7 +387,7 @@
      */
     public void quadTo(float x1, float y1, float x2, float y2) {
         isSimplePath = false;
-        native_quadTo(mNativePath, x1, y1, x2, y2);
+        nQuadTo(mNativePath, x1, y1, x2, y2);
     }
 
     /**
@@ -403,7 +406,7 @@
      */
     public void rQuadTo(float dx1, float dy1, float dx2, float dy2) {
         isSimplePath = false;
-        native_rQuadTo(mNativePath, dx1, dy1, dx2, dy2);
+        nRQuadTo(mNativePath, dx1, dy1, dx2, dy2);
     }
 
     /**
@@ -421,7 +424,7 @@
     public void cubicTo(float x1, float y1, float x2, float y2,
                         float x3, float y3) {
         isSimplePath = false;
-        native_cubicTo(mNativePath, x1, y1, x2, y2, x3, y3);
+        nCubicTo(mNativePath, x1, y1, x2, y2, x3, y3);
     }
 
     /**
@@ -432,7 +435,7 @@
     public void rCubicTo(float x1, float y1, float x2, float y2,
                          float x3, float y3) {
         isSimplePath = false;
-        native_rCubicTo(mNativePath, x1, y1, x2, y2, x3, y3);
+        nRCubicTo(mNativePath, x1, y1, x2, y2, x3, y3);
     }
 
     /**
@@ -483,7 +486,7 @@
     public void arcTo(float left, float top, float right, float bottom, float startAngle,
             float sweepAngle, boolean forceMoveTo) {
         isSimplePath = false;
-        native_arcTo(mNativePath, left, top, right, bottom, startAngle, sweepAngle, forceMoveTo);
+        nArcTo(mNativePath, left, top, right, bottom, startAngle, sweepAngle, forceMoveTo);
     }
 
     /**
@@ -492,7 +495,7 @@
      */
     public void close() {
         isSimplePath = false;
-        native_close(mNativePath);
+        nClose(mNativePath);
     }
 
     /**
@@ -544,7 +547,7 @@
      */
     public void addRect(float left, float top, float right, float bottom, Direction dir) {
         detectSimplePath(left, top, right, bottom, dir);
-        native_addRect(mNativePath, left, top, right, bottom, dir.nativeInt);
+        nAddRect(mNativePath, left, top, right, bottom, dir.nativeInt);
     }
 
     /**
@@ -564,7 +567,7 @@
      */
     public void addOval(float left, float top, float right, float bottom, Direction dir) {
         isSimplePath = false;
-        native_addOval(mNativePath, left, top, right, bottom, dir.nativeInt);
+        nAddOval(mNativePath, left, top, right, bottom, dir.nativeInt);
     }
 
     /**
@@ -577,7 +580,7 @@
      */
     public void addCircle(float x, float y, float radius, Direction dir) {
         isSimplePath = false;
-        native_addCircle(mNativePath, x, y, radius, dir.nativeInt);
+        nAddCircle(mNativePath, x, y, radius, dir.nativeInt);
     }
 
     /**
@@ -600,7 +603,7 @@
     public void addArc(float left, float top, float right, float bottom, float startAngle,
             float sweepAngle) {
         isSimplePath = false;
-        native_addArc(mNativePath, left, top, right, bottom, startAngle, sweepAngle);
+        nAddArc(mNativePath, left, top, right, bottom, startAngle, sweepAngle);
     }
 
     /**
@@ -625,7 +628,7 @@
     public void addRoundRect(float left, float top, float right, float bottom, float rx, float ry,
             Direction dir) {
         isSimplePath = false;
-        native_addRoundRect(mNativePath, left, top, right, bottom, rx, ry, dir.nativeInt);
+        nAddRoundRect(mNativePath, left, top, right, bottom, rx, ry, dir.nativeInt);
     }
 
     /**
@@ -658,7 +661,7 @@
             throw new ArrayIndexOutOfBoundsException("radii[] needs 8 values");
         }
         isSimplePath = false;
-        native_addRoundRect(mNativePath, left, top, right, bottom, radii, dir.nativeInt);
+        nAddRoundRect(mNativePath, left, top, right, bottom, radii, dir.nativeInt);
     }
 
     /**
@@ -669,7 +672,7 @@
      */
     public void addPath(Path src, float dx, float dy) {
         isSimplePath = false;
-        native_addPath(mNativePath, src.mNativePath, dx, dy);
+        nAddPath(mNativePath, src.mNativePath, dx, dy);
     }
 
     /**
@@ -679,7 +682,7 @@
      */
     public void addPath(Path src) {
         isSimplePath = false;
-        native_addPath(mNativePath, src.mNativePath);
+        nAddPath(mNativePath, src.mNativePath);
     }
 
     /**
@@ -689,7 +692,7 @@
      */
     public void addPath(Path src, Matrix matrix) {
         if (!src.isSimplePath) isSimplePath = false;
-        native_addPath(mNativePath, src.mNativePath, matrix.native_instance);
+        nAddPath(mNativePath, src.mNativePath, matrix.native_instance);
     }
 
     /**
@@ -725,7 +728,7 @@
         } else {
             isSimplePath = false;
         }
-        native_offset(mNativePath, dx, dy);
+        nOffset(mNativePath, dx, dy);
     }
 
     /**
@@ -736,7 +739,7 @@
      */
     public void setLastPoint(float dx, float dy) {
         isSimplePath = false;
-        native_setLastPoint(mNativePath, dx, dy);
+        nSetLastPoint(mNativePath, dx, dy);
     }
 
     /**
@@ -753,7 +756,7 @@
             dst.isSimplePath = false;
             dstNative = dst.mNativePath;
         }
-        native_transform(mNativePath, matrix.native_instance, dstNative);
+        nTransform(mNativePath, matrix.native_instance, dstNative);
     }
 
     /**
@@ -763,12 +766,12 @@
      */
     public void transform(Matrix matrix) {
         isSimplePath = false;
-        native_transform(mNativePath, matrix.native_instance);
+        nTransform(mNativePath, matrix.native_instance);
     }
 
     protected void finalize() throws Throwable {
         try {
-            finalizer(mNativePath);
+            nFinalize(mNativePath);
             mNativePath = 0;  //  Other finalizers can still call us.
         } finally {
             super.finalize();
@@ -803,59 +806,68 @@
      * @return An array of components for points approximating the Path.
      */
     public float[] approximate(float acceptableError) {
-        return native_approximate(mNativePath, acceptableError);
+        return nApproximate(mNativePath, acceptableError);
     }
 
-    private static native long init1();
-    private static native long init2(long nPath);
-    private static native void native_reset(long nPath);
-    private static native void native_rewind(long nPath);
-    private static native void native_set(long native_dst, long native_src);
-    private static native boolean native_isConvex(long nPath);
-    private static native int native_getFillType(long nPath);
-    private static native void native_setFillType(long nPath, int ft);
-    private static native boolean native_isEmpty(long nPath);
-    private static native boolean native_isRect(long nPath, RectF rect);
-    private static native void native_computeBounds(long nPath, RectF bounds);
-    private static native void native_incReserve(long nPath, int extraPtCount);
-    private static native void native_moveTo(long nPath, float x, float y);
-    private static native void native_rMoveTo(long nPath, float dx, float dy);
-    private static native void native_lineTo(long nPath, float x, float y);
-    private static native void native_rLineTo(long nPath, float dx, float dy);
-    private static native void native_quadTo(long nPath, float x1, float y1,
-                                             float x2, float y2);
-    private static native void native_rQuadTo(long nPath, float dx1, float dy1,
-                                              float dx2, float dy2);
-    private static native void native_cubicTo(long nPath, float x1, float y1,
-                                        float x2, float y2, float x3, float y3);
-    private static native void native_rCubicTo(long nPath, float x1, float y1,
-                                        float x2, float y2, float x3, float y3);
-    private static native void native_arcTo(long nPath, float left, float top,
-                                            float right, float bottom, float startAngle,
-                                            float sweepAngle, boolean forceMoveTo);
-    private static native void native_close(long nPath);
-    private static native void native_addRect(long nPath, float left, float top,
-                                            float right, float bottom, int dir);
-    private static native void native_addOval(long nPath, float left, float top,
+    // ------------------ Regular JNI ------------------------
+
+    private static native long nInit();
+    private static native long nInit(long nPath);
+    private static native void nFinalize(long nPath);
+    private static native void nSet(long native_dst, long nSrc);
+    private static native void nComputeBounds(long nPath, RectF bounds);
+    private static native void nIncReserve(long nPath, int extraPtCount);
+    private static native void nMoveTo(long nPath, float x, float y);
+    private static native void nRMoveTo(long nPath, float dx, float dy);
+    private static native void nLineTo(long nPath, float x, float y);
+    private static native void nRLineTo(long nPath, float dx, float dy);
+    private static native void nQuadTo(long nPath, float x1, float y1, float x2, float y2);
+    private static native void nRQuadTo(long nPath, float dx1, float dy1, float dx2, float dy2);
+    private static native void nCubicTo(long nPath, float x1, float y1, float x2, float y2,
+            float x3, float y3);
+    private static native void nRCubicTo(long nPath, float x1, float y1, float x2, float y2,
+            float x3, float y3);
+    private static native void nArcTo(long nPath, float left, float top, float right, float bottom,
+            float startAngle, float sweepAngle, boolean forceMoveTo);
+    private static native void nClose(long nPath);
+    private static native void nAddRect(long nPath, float left, float top,
             float right, float bottom, int dir);
-    private static native void native_addCircle(long nPath, float x, float y, float radius, int dir);
-    private static native void native_addArc(long nPath, float left, float top,
-                                             float right, float bottom,
-                                             float startAngle, float sweepAngle);
-    private static native void native_addRoundRect(long nPath, float left, float top,
-                                                   float right, float bottom,
-                                                   float rx, float ry, int dir);
-    private static native void native_addRoundRect(long nPath, float left, float top,
-                                                   float right, float bottom,
-                                                   float[] radii, int dir);
-    private static native void native_addPath(long nPath, long src, float dx, float dy);
-    private static native void native_addPath(long nPath, long src);
-    private static native void native_addPath(long nPath, long src, long matrix);
-    private static native void native_offset(long nPath, float dx, float dy);
-    private static native void native_setLastPoint(long nPath, float dx, float dy);
-    private static native void native_transform(long nPath, long matrix, long dst_path);
-    private static native void native_transform(long nPath, long matrix);
-    private static native boolean native_op(long path1, long path2, int op, long result);
-    private static native void finalizer(long nPath);
-    private static native float[] native_approximate(long nPath, float error);
+    private static native void nAddOval(long nPath, float left, float top,
+            float right, float bottom, int dir);
+    private static native void nAddCircle(long nPath, float x, float y, float radius, int dir);
+    private static native void nAddArc(long nPath, float left, float top, float right, float bottom,
+            float startAngle, float sweepAngle);
+    private static native void nAddRoundRect(long nPath, float left, float top,
+            float right, float bottom, float rx, float ry, int dir);
+    private static native void nAddRoundRect(long nPath, float left, float top,
+            float right, float bottom, float[] radii, int dir);
+    private static native void nAddPath(long nPath, long src, float dx, float dy);
+    private static native void nAddPath(long nPath, long src);
+    private static native void nAddPath(long nPath, long src, long matrix);
+    private static native void nOffset(long nPath, float dx, float dy);
+    private static native void nSetLastPoint(long nPath, float dx, float dy);
+    private static native void nTransform(long nPath, long matrix, long dst_path);
+    private static native void nTransform(long nPath, long matrix);
+    private static native boolean nOp(long path1, long path2, int op, long result);
+    private static native float[] nApproximate(long nPath, float error);
+
+    // ------------------ Fast JNI ------------------------
+
+    @FastNative
+    private static native boolean nIsRect(long nPath, RectF rect);
+
+    // ------------------ Critical JNI ------------------------
+
+    @CriticalNative
+    private static native void nReset(long nPath);
+    @CriticalNative
+    private static native void nRewind(long nPath);
+    @CriticalNative
+    private static native boolean nIsEmpty(long nPath);
+    @CriticalNative
+    private static native boolean nIsConvex(long nPath);
+    @CriticalNative
+    private static native int nGetFillType(long nPath);
+    @CriticalNative
+    private static native void nSetFillType(long nPath, int ft);
 }