xref: /aosp_15_r20/frameworks/base/libs/hwui/jni/PathMeasure.cpp (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1*d57664e9SAndroid Build Coastguard Worker /* libs/android_runtime/android/graphics/PathMeasure.cpp
2*d57664e9SAndroid Build Coastguard Worker **
3*d57664e9SAndroid Build Coastguard Worker ** Copyright 2007, The Android Open Source Project
4*d57664e9SAndroid Build Coastguard Worker **
5*d57664e9SAndroid Build Coastguard Worker ** Licensed under the Apache License, Version 2.0 (the "License");
6*d57664e9SAndroid Build Coastguard Worker ** you may not use this file except in compliance with the License.
7*d57664e9SAndroid Build Coastguard Worker ** You may obtain a copy of the License at
8*d57664e9SAndroid Build Coastguard Worker **
9*d57664e9SAndroid Build Coastguard Worker **     http://www.apache.org/licenses/LICENSE-2.0
10*d57664e9SAndroid Build Coastguard Worker **
11*d57664e9SAndroid Build Coastguard Worker ** Unless required by applicable law or agreed to in writing, software
12*d57664e9SAndroid Build Coastguard Worker ** distributed under the License is distributed on an "AS IS" BASIS,
13*d57664e9SAndroid Build Coastguard Worker ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*d57664e9SAndroid Build Coastguard Worker ** See the License for the specific language governing permissions and
15*d57664e9SAndroid Build Coastguard Worker ** limitations under the License.
16*d57664e9SAndroid Build Coastguard Worker */
17*d57664e9SAndroid Build Coastguard Worker 
18*d57664e9SAndroid Build Coastguard Worker #include "GraphicsJNI.h"
19*d57664e9SAndroid Build Coastguard Worker 
20*d57664e9SAndroid Build Coastguard Worker #include "SkMatrix.h"
21*d57664e9SAndroid Build Coastguard Worker #include "SkPath.h"
22*d57664e9SAndroid Build Coastguard Worker #include "SkPathMeasure.h"
23*d57664e9SAndroid Build Coastguard Worker #include "SkPoint.h"
24*d57664e9SAndroid Build Coastguard Worker #include "SkScalar.h"
25*d57664e9SAndroid Build Coastguard Worker 
26*d57664e9SAndroid Build Coastguard Worker /*  We declare an explicit pair, so that we don't have to rely on the java
27*d57664e9SAndroid Build Coastguard Worker     client to be sure not to edit the path while we have an active measure
28*d57664e9SAndroid Build Coastguard Worker     object associated with it.
29*d57664e9SAndroid Build Coastguard Worker 
30*d57664e9SAndroid Build Coastguard Worker     This costs us the copy of the path, for the sake of not allowing a bad
31*d57664e9SAndroid Build Coastguard Worker     java client to randomly crash (since we can't detect the case where the
32*d57664e9SAndroid Build Coastguard Worker     native path has been modified).
33*d57664e9SAndroid Build Coastguard Worker 
34*d57664e9SAndroid Build Coastguard Worker     The C side does have this risk, but it chooses for speed over safety. If it
35*d57664e9SAndroid Build Coastguard Worker     later changes this, and is internally safe from changes to the path, then
36*d57664e9SAndroid Build Coastguard Worker     we can remove this explicit copy from our JNI code.
37*d57664e9SAndroid Build Coastguard Worker 
38*d57664e9SAndroid Build Coastguard Worker     Note that we do not have a reference on the java side to the java path.
39*d57664e9SAndroid Build Coastguard Worker     Were we to not need the native copy here, we would want to add a java
40*d57664e9SAndroid Build Coastguard Worker     reference, so that the java path would not get GD'd while the measure object
41*d57664e9SAndroid Build Coastguard Worker     was still alive.
42*d57664e9SAndroid Build Coastguard Worker */
43*d57664e9SAndroid Build Coastguard Worker struct PathMeasurePair {
PathMeasurePairPathMeasurePair44*d57664e9SAndroid Build Coastguard Worker     PathMeasurePair() {}
PathMeasurePairPathMeasurePair45*d57664e9SAndroid Build Coastguard Worker     PathMeasurePair(const SkPath& path, bool forceClosed)
46*d57664e9SAndroid Build Coastguard Worker         : fPath(path), fMeasure(fPath, forceClosed) {}
47*d57664e9SAndroid Build Coastguard Worker 
48*d57664e9SAndroid Build Coastguard Worker     SkPath          fPath;      // copy of the user's path
49*d57664e9SAndroid Build Coastguard Worker     SkPathMeasure   fMeasure;   // this guy points to fPath
50*d57664e9SAndroid Build Coastguard Worker };
51*d57664e9SAndroid Build Coastguard Worker 
52*d57664e9SAndroid Build Coastguard Worker namespace android {
53*d57664e9SAndroid Build Coastguard Worker 
54*d57664e9SAndroid Build Coastguard Worker class SkPathMeasureGlue {
55*d57664e9SAndroid Build Coastguard Worker public:
56*d57664e9SAndroid Build Coastguard Worker 
create(JNIEnv * env,jobject clazz,jlong pathHandle,jboolean forceClosedHandle)57*d57664e9SAndroid Build Coastguard Worker     static jlong create(JNIEnv* env, jobject clazz, jlong pathHandle,
58*d57664e9SAndroid Build Coastguard Worker                         jboolean forceClosedHandle) {
59*d57664e9SAndroid Build Coastguard Worker         const SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
60*d57664e9SAndroid Build Coastguard Worker         bool forceClosed = (forceClosedHandle == JNI_TRUE);
61*d57664e9SAndroid Build Coastguard Worker         PathMeasurePair* pair;
62*d57664e9SAndroid Build Coastguard Worker         if(path)
63*d57664e9SAndroid Build Coastguard Worker             pair = new PathMeasurePair(*path, forceClosed);
64*d57664e9SAndroid Build Coastguard Worker         else
65*d57664e9SAndroid Build Coastguard Worker             pair = new PathMeasurePair;
66*d57664e9SAndroid Build Coastguard Worker         return reinterpret_cast<jlong>(pair);
67*d57664e9SAndroid Build Coastguard Worker     }
68*d57664e9SAndroid Build Coastguard Worker 
setPath(JNIEnv * env,jobject clazz,jlong pairHandle,jlong pathHandle,jboolean forceClosedHandle)69*d57664e9SAndroid Build Coastguard Worker     static void setPath(JNIEnv* env, jobject clazz, jlong pairHandle,
70*d57664e9SAndroid Build Coastguard Worker                         jlong pathHandle, jboolean forceClosedHandle) {
71*d57664e9SAndroid Build Coastguard Worker         PathMeasurePair* pair = reinterpret_cast<PathMeasurePair*>(pairHandle);
72*d57664e9SAndroid Build Coastguard Worker         const SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
73*d57664e9SAndroid Build Coastguard Worker         bool forceClosed = (forceClosedHandle == JNI_TRUE);
74*d57664e9SAndroid Build Coastguard Worker 
75*d57664e9SAndroid Build Coastguard Worker         if (NULL == path) {
76*d57664e9SAndroid Build Coastguard Worker             pair->fPath.reset();
77*d57664e9SAndroid Build Coastguard Worker         } else {
78*d57664e9SAndroid Build Coastguard Worker             pair->fPath = *path;
79*d57664e9SAndroid Build Coastguard Worker         }
80*d57664e9SAndroid Build Coastguard Worker         pair->fMeasure.setPath(&pair->fPath, forceClosed);
81*d57664e9SAndroid Build Coastguard Worker     }
82*d57664e9SAndroid Build Coastguard Worker 
getLength(JNIEnv * env,jobject clazz,jlong pairHandle)83*d57664e9SAndroid Build Coastguard Worker     static jfloat getLength(JNIEnv* env, jobject clazz, jlong pairHandle) {
84*d57664e9SAndroid Build Coastguard Worker         PathMeasurePair* pair = reinterpret_cast<PathMeasurePair*>(pairHandle);
85*d57664e9SAndroid Build Coastguard Worker         return static_cast<jfloat>(SkScalarToFloat(pair->fMeasure.getLength()));
86*d57664e9SAndroid Build Coastguard Worker     }
87*d57664e9SAndroid Build Coastguard Worker 
convertTwoElemFloatArray(JNIEnv * env,jfloatArray array,const SkScalar src[2])88*d57664e9SAndroid Build Coastguard Worker     static void convertTwoElemFloatArray(JNIEnv* env, jfloatArray array, const SkScalar src[2]) {
89*d57664e9SAndroid Build Coastguard Worker         AutoJavaFloatArray autoArray(env, array, 2);
90*d57664e9SAndroid Build Coastguard Worker         jfloat* ptr = autoArray.ptr();
91*d57664e9SAndroid Build Coastguard Worker         ptr[0] = SkScalarToFloat(src[0]);
92*d57664e9SAndroid Build Coastguard Worker         ptr[1] = SkScalarToFloat(src[1]);
93*d57664e9SAndroid Build Coastguard Worker     }
94*d57664e9SAndroid Build Coastguard Worker 
getPosTan(JNIEnv * env,jobject clazz,jlong pairHandle,jfloat dist,jfloatArray pos,jfloatArray tan)95*d57664e9SAndroid Build Coastguard Worker     static jboolean getPosTan(JNIEnv* env, jobject clazz, jlong pairHandle, jfloat dist, jfloatArray pos, jfloatArray tan) {
96*d57664e9SAndroid Build Coastguard Worker         PathMeasurePair* pair = reinterpret_cast<PathMeasurePair*>(pairHandle);
97*d57664e9SAndroid Build Coastguard Worker         SkScalar    tmpPos[2], tmpTan[2];
98*d57664e9SAndroid Build Coastguard Worker         SkScalar*   posPtr = pos ? tmpPos : NULL;
99*d57664e9SAndroid Build Coastguard Worker         SkScalar*   tanPtr = tan ? tmpTan : NULL;
100*d57664e9SAndroid Build Coastguard Worker 
101*d57664e9SAndroid Build Coastguard Worker         if (!pair->fMeasure.getPosTan(dist, (SkPoint*)posPtr, (SkVector*)tanPtr)) {
102*d57664e9SAndroid Build Coastguard Worker             return JNI_FALSE;
103*d57664e9SAndroid Build Coastguard Worker         }
104*d57664e9SAndroid Build Coastguard Worker 
105*d57664e9SAndroid Build Coastguard Worker         if (pos) {
106*d57664e9SAndroid Build Coastguard Worker             convertTwoElemFloatArray(env, pos, tmpPos);
107*d57664e9SAndroid Build Coastguard Worker         }
108*d57664e9SAndroid Build Coastguard Worker         if (tan) {
109*d57664e9SAndroid Build Coastguard Worker             convertTwoElemFloatArray(env, tan, tmpTan);
110*d57664e9SAndroid Build Coastguard Worker         }
111*d57664e9SAndroid Build Coastguard Worker         return JNI_TRUE;
112*d57664e9SAndroid Build Coastguard Worker     }
113*d57664e9SAndroid Build Coastguard Worker 
getMatrix(JNIEnv * env,jobject clazz,jlong pairHandle,jfloat dist,jlong matrixHandle,jint flags)114*d57664e9SAndroid Build Coastguard Worker     static jboolean getMatrix(JNIEnv* env, jobject clazz, jlong pairHandle, jfloat dist,
115*d57664e9SAndroid Build Coastguard Worker                           jlong matrixHandle, jint flags) {
116*d57664e9SAndroid Build Coastguard Worker         PathMeasurePair* pair = reinterpret_cast<PathMeasurePair*>(pairHandle);
117*d57664e9SAndroid Build Coastguard Worker         SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
118*d57664e9SAndroid Build Coastguard Worker         bool result = pair->fMeasure.getMatrix(dist, matrix, (SkPathMeasure::MatrixFlags)flags);
119*d57664e9SAndroid Build Coastguard Worker         return result ? JNI_TRUE : JNI_FALSE;
120*d57664e9SAndroid Build Coastguard Worker     }
121*d57664e9SAndroid Build Coastguard Worker 
getSegment(JNIEnv * env,jobject clazz,jlong pairHandle,jfloat startF,jfloat stopF,jlong dstHandle,jboolean startWithMoveTo)122*d57664e9SAndroid Build Coastguard Worker     static jboolean getSegment(JNIEnv* env, jobject clazz, jlong pairHandle, jfloat startF,
123*d57664e9SAndroid Build Coastguard Worker                                jfloat stopF, jlong dstHandle, jboolean startWithMoveTo) {
124*d57664e9SAndroid Build Coastguard Worker         PathMeasurePair* pair = reinterpret_cast<PathMeasurePair*>(pairHandle);
125*d57664e9SAndroid Build Coastguard Worker         SkPath* dst = reinterpret_cast<SkPath*>(dstHandle);
126*d57664e9SAndroid Build Coastguard Worker         bool result = pair->fMeasure.getSegment(startF, stopF, dst, startWithMoveTo);
127*d57664e9SAndroid Build Coastguard Worker         return result ? JNI_TRUE : JNI_FALSE;
128*d57664e9SAndroid Build Coastguard Worker     }
129*d57664e9SAndroid Build Coastguard Worker 
isClosed(JNIEnv * env,jobject clazz,jlong pairHandle)130*d57664e9SAndroid Build Coastguard Worker     static jboolean isClosed(JNIEnv* env, jobject clazz, jlong pairHandle) {
131*d57664e9SAndroid Build Coastguard Worker         PathMeasurePair* pair = reinterpret_cast<PathMeasurePair*>(pairHandle);
132*d57664e9SAndroid Build Coastguard Worker         bool result = pair->fMeasure.isClosed();
133*d57664e9SAndroid Build Coastguard Worker         return result ? JNI_TRUE : JNI_FALSE;
134*d57664e9SAndroid Build Coastguard Worker     }
135*d57664e9SAndroid Build Coastguard Worker 
nextContour(JNIEnv * env,jobject clazz,jlong pairHandle)136*d57664e9SAndroid Build Coastguard Worker     static jboolean nextContour(JNIEnv* env, jobject clazz, jlong pairHandle) {
137*d57664e9SAndroid Build Coastguard Worker         PathMeasurePair* pair = reinterpret_cast<PathMeasurePair*>(pairHandle);
138*d57664e9SAndroid Build Coastguard Worker         bool result = pair->fMeasure.nextContour();
139*d57664e9SAndroid Build Coastguard Worker         return result ? JNI_TRUE : JNI_FALSE;
140*d57664e9SAndroid Build Coastguard Worker     }
141*d57664e9SAndroid Build Coastguard Worker 
destroy(JNIEnv * env,jobject clazz,jlong pairHandle)142*d57664e9SAndroid Build Coastguard Worker     static void destroy(JNIEnv* env, jobject clazz, jlong pairHandle) {
143*d57664e9SAndroid Build Coastguard Worker         PathMeasurePair* pair = reinterpret_cast<PathMeasurePair*>(pairHandle);
144*d57664e9SAndroid Build Coastguard Worker         delete pair;
145*d57664e9SAndroid Build Coastguard Worker     }
146*d57664e9SAndroid Build Coastguard Worker };
147*d57664e9SAndroid Build Coastguard Worker 
148*d57664e9SAndroid Build Coastguard Worker static const JNINativeMethod methods[] = {
149*d57664e9SAndroid Build Coastguard Worker     {"native_create",       "(JZ)J",        (void*) SkPathMeasureGlue::create      },
150*d57664e9SAndroid Build Coastguard Worker     {"native_setPath",      "(JJZ)V",       (void*) SkPathMeasureGlue::setPath     },
151*d57664e9SAndroid Build Coastguard Worker     {"native_getLength",    "(J)F",         (void*) SkPathMeasureGlue::getLength   },
152*d57664e9SAndroid Build Coastguard Worker     {"native_getPosTan",    "(JF[F[F)Z",    (void*) SkPathMeasureGlue::getPosTan   },
153*d57664e9SAndroid Build Coastguard Worker     {"native_getMatrix",    "(JFJI)Z",      (void*) SkPathMeasureGlue::getMatrix   },
154*d57664e9SAndroid Build Coastguard Worker     {"native_getSegment",   "(JFFJZ)Z",     (void*) SkPathMeasureGlue::getSegment  },
155*d57664e9SAndroid Build Coastguard Worker     {"native_isClosed",     "(J)Z",         (void*) SkPathMeasureGlue::isClosed    },
156*d57664e9SAndroid Build Coastguard Worker     {"native_nextContour",  "(J)Z",         (void*) SkPathMeasureGlue::nextContour },
157*d57664e9SAndroid Build Coastguard Worker     {"native_destroy",      "(J)V",         (void*) SkPathMeasureGlue::destroy     }
158*d57664e9SAndroid Build Coastguard Worker };
159*d57664e9SAndroid Build Coastguard Worker 
register_android_graphics_PathMeasure(JNIEnv * env)160*d57664e9SAndroid Build Coastguard Worker int register_android_graphics_PathMeasure(JNIEnv* env) {
161*d57664e9SAndroid Build Coastguard Worker     return RegisterMethodsOrDie(env, "android/graphics/PathMeasure", methods, NELEM(methods));
162*d57664e9SAndroid Build Coastguard Worker }
163*d57664e9SAndroid Build Coastguard Worker 
164*d57664e9SAndroid Build Coastguard Worker }
165