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