| /* 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 "SkMatrix.h" |
| #include "SkPath.h" |
| #include "SkPathMeasure.h" |
| #include "SkPoint.h" |
| #include "SkScalar.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)); |
| } |
| |
| } |