summaryrefslogtreecommitdiff
path: root/libs/hwui/jni/PathMeasure.cpp
diff options
context:
space:
mode:
authorXin Li <delphij@google.com>2020-08-31 21:21:38 -0700
committerXin Li <delphij@google.com>2020-08-31 21:21:38 -0700
commit628590d7ec80e10a3fc24b1c18a1afb55cca10a8 (patch)
tree4b1c3f52d86d7fb53afbe9e9438468588fa489f8 /libs/hwui/jni/PathMeasure.cpp
parentb11b8ec3aec8bb42f2c07e1c5ac7942da293baa8 (diff)
parentd2d3a20624d968199353ccf6ddbae6f3ac39c9af (diff)
Merge Android R (rvc-dev-plus-aosp-without-vendor@6692709)
Bug: 166295507 Merged-In: I3d92a6de21a938f6b352ec26dc23420c0fe02b27 Change-Id: Ifdb80563ef042738778ebb8a7581a97c4e3d96e2
Diffstat (limited to 'libs/hwui/jni/PathMeasure.cpp')
-rw-r--r--libs/hwui/jni/PathMeasure.cpp160
1 files changed, 160 insertions, 0 deletions
diff --git a/libs/hwui/jni/PathMeasure.cpp b/libs/hwui/jni/PathMeasure.cpp
new file mode 100644
index 000000000000..acf893e9544c
--- /dev/null
+++ b/libs/hwui/jni/PathMeasure.cpp
@@ -0,0 +1,160 @@
+/* libs/android_runtime/android/graphics/PathMeasure.cpp
+**
+** Copyright 2007, 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.
+*/
+
+#include "GraphicsJNI.h"
+
+#include "SkPathMeasure.h"
+
+/* We declare an explicit pair, so that we don't have to rely on the java
+ client to be sure not to edit the path while we have an active measure
+ object associated with it.
+
+ This costs us the copy of the path, for the sake of not allowing a bad
+ java client to randomly crash (since we can't detect the case where the
+ native path has been modified).
+
+ The C side does have this risk, but it chooses for speed over safety. If it
+ later changes this, and is internally safe from changes to the path, then
+ we can remove this explicit copy from our JNI code.
+
+ Note that we do not have a reference on the java side to the java path.
+ Were we to not need the native copy here, we would want to add a java
+ reference, so that the java path would not get GD'd while the measure object
+ was still alive.
+*/
+struct PathMeasurePair {
+ PathMeasurePair() {}
+ PathMeasurePair(const SkPath& path, bool forceClosed)
+ : fPath(path), fMeasure(fPath, forceClosed) {}
+
+ SkPath fPath; // copy of the user's path
+ SkPathMeasure fMeasure; // this guy points to fPath
+};
+
+namespace android {
+
+class SkPathMeasureGlue {
+public:
+
+ static jlong create(JNIEnv* env, jobject clazz, jlong pathHandle,
+ jboolean forceClosedHandle) {
+ const SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
+ bool forceClosed = (forceClosedHandle == JNI_TRUE);
+ PathMeasurePair* pair;
+ if(path)
+ pair = new PathMeasurePair(*path, forceClosed);
+ else
+ pair = new PathMeasurePair;
+ return reinterpret_cast<jlong>(pair);
+ }
+
+ static void setPath(JNIEnv* env, jobject clazz, jlong pairHandle,
+ jlong pathHandle, jboolean forceClosedHandle) {
+ PathMeasurePair* pair = reinterpret_cast<PathMeasurePair*>(pairHandle);
+ const SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
+ bool forceClosed = (forceClosedHandle == JNI_TRUE);
+
+ if (NULL == path) {
+ pair->fPath.reset();
+ } else {
+ pair->fPath = *path;
+ }
+ pair->fMeasure.setPath(&pair->fPath, forceClosed);
+ }
+
+ static jfloat getLength(JNIEnv* env, jobject clazz, jlong pairHandle) {
+ PathMeasurePair* pair = reinterpret_cast<PathMeasurePair*>(pairHandle);
+ return static_cast<jfloat>(SkScalarToFloat(pair->fMeasure.getLength()));
+ }
+
+ static void convertTwoElemFloatArray(JNIEnv* env, jfloatArray array, const SkScalar src[2]) {
+ AutoJavaFloatArray autoArray(env, array, 2);
+ jfloat* ptr = autoArray.ptr();
+ ptr[0] = SkScalarToFloat(src[0]);
+ ptr[1] = SkScalarToFloat(src[1]);
+ }
+
+ static jboolean getPosTan(JNIEnv* env, jobject clazz, jlong pairHandle, jfloat dist, jfloatArray pos, jfloatArray tan) {
+ PathMeasurePair* pair = reinterpret_cast<PathMeasurePair*>(pairHandle);
+ SkScalar tmpPos[2], tmpTan[2];
+ SkScalar* posPtr = pos ? tmpPos : NULL;
+ SkScalar* tanPtr = tan ? tmpTan : NULL;
+
+ if (!pair->fMeasure.getPosTan(dist, (SkPoint*)posPtr, (SkVector*)tanPtr)) {
+ return JNI_FALSE;
+ }
+
+ if (pos) {
+ convertTwoElemFloatArray(env, pos, tmpPos);
+ }
+ if (tan) {
+ convertTwoElemFloatArray(env, tan, tmpTan);
+ }
+ return JNI_TRUE;
+ }
+
+ static jboolean getMatrix(JNIEnv* env, jobject clazz, jlong pairHandle, jfloat dist,
+ jlong matrixHandle, jint flags) {
+ PathMeasurePair* pair = reinterpret_cast<PathMeasurePair*>(pairHandle);
+ SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
+ bool result = pair->fMeasure.getMatrix(dist, matrix, (SkPathMeasure::MatrixFlags)flags);
+ return result ? JNI_TRUE : JNI_FALSE;
+ }
+
+ static jboolean getSegment(JNIEnv* env, jobject clazz, jlong pairHandle, jfloat startF,
+ jfloat stopF, jlong dstHandle, jboolean startWithMoveTo) {
+ PathMeasurePair* pair = reinterpret_cast<PathMeasurePair*>(pairHandle);
+ SkPath* dst = reinterpret_cast<SkPath*>(dstHandle);
+ bool result = pair->fMeasure.getSegment(startF, stopF, dst, startWithMoveTo);
+ return result ? JNI_TRUE : JNI_FALSE;
+ }
+
+ static jboolean isClosed(JNIEnv* env, jobject clazz, jlong pairHandle) {
+ PathMeasurePair* pair = reinterpret_cast<PathMeasurePair*>(pairHandle);
+ bool result = pair->fMeasure.isClosed();
+ return result ? JNI_TRUE : JNI_FALSE;
+ }
+
+ static jboolean nextContour(JNIEnv* env, jobject clazz, jlong pairHandle) {
+ PathMeasurePair* pair = reinterpret_cast<PathMeasurePair*>(pairHandle);
+ bool result = pair->fMeasure.nextContour();
+ return result ? JNI_TRUE : JNI_FALSE;
+ }
+
+ static void destroy(JNIEnv* env, jobject clazz, jlong pairHandle) {
+ PathMeasurePair* pair = reinterpret_cast<PathMeasurePair*>(pairHandle);
+ delete pair;
+ }
+};
+
+static const JNINativeMethod methods[] = {
+ {"native_create", "(JZ)J", (void*) SkPathMeasureGlue::create },
+ {"native_setPath", "(JJZ)V", (void*) SkPathMeasureGlue::setPath },
+ {"native_getLength", "(J)F", (void*) SkPathMeasureGlue::getLength },
+ {"native_getPosTan", "(JF[F[F)Z", (void*) SkPathMeasureGlue::getPosTan },
+ {"native_getMatrix", "(JFJI)Z", (void*) SkPathMeasureGlue::getMatrix },
+ {"native_getSegment", "(JFFJZ)Z", (void*) SkPathMeasureGlue::getSegment },
+ {"native_isClosed", "(J)Z", (void*) SkPathMeasureGlue::isClosed },
+ {"native_nextContour", "(J)Z", (void*) SkPathMeasureGlue::nextContour },
+ {"native_destroy", "(J)V", (void*) SkPathMeasureGlue::destroy }
+};
+
+int register_android_graphics_PathMeasure(JNIEnv* env) {
+ return RegisterMethodsOrDie(env, "android/graphics/PathMeasure", methods, NELEM(methods));
+}
+
+}