139 lines
5.4 KiB
C++
139 lines
5.4 KiB
C++
|
/* 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 "jni.h"
|
||
|
#include "GraphicsJNI.h"
|
||
|
#include <android_runtime/AndroidRuntime.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 PathMeasurePair* create(JNIEnv* env, jobject clazz, const SkPath* path, jboolean forceClosed) {
|
||
|
return path ? new PathMeasurePair(*path, forceClosed) : new PathMeasurePair;
|
||
|
}
|
||
|
|
||
|
static void setPath(JNIEnv* env, jobject clazz, PathMeasurePair* pair, const SkPath* path, jboolean forceClosed) {
|
||
|
if (NULL == path) {
|
||
|
pair->fPath.reset();
|
||
|
} else {
|
||
|
pair->fPath = *path;
|
||
|
}
|
||
|
pair->fMeasure.setPath(&pair->fPath, forceClosed);
|
||
|
}
|
||
|
|
||
|
static jfloat getLength(JNIEnv* env, jobject clazz, PathMeasurePair* pair) {
|
||
|
return 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, PathMeasurePair* pair, jfloat dist, jfloatArray pos, jfloatArray tan) {
|
||
|
SkScalar tmpPos[2], tmpTan[2];
|
||
|
SkScalar* posPtr = pos ? tmpPos : NULL;
|
||
|
SkScalar* tanPtr = tan ? tmpTan : NULL;
|
||
|
|
||
|
if (!pair->fMeasure.getPosTan(SkFloatToScalar(dist), (SkPoint*)posPtr, (SkVector*)tanPtr)) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (pos) {
|
||
|
convertTwoElemFloatArray(env, pos, tmpPos);
|
||
|
}
|
||
|
if (tan) {
|
||
|
convertTwoElemFloatArray(env, tan, tmpTan);
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
static jboolean getMatrix(JNIEnv* env, jobject clazz, PathMeasurePair* pair, jfloat dist,
|
||
|
SkMatrix* matrix, int flags) {
|
||
|
return pair->fMeasure.getMatrix(SkFloatToScalar(dist), matrix, (SkPathMeasure::MatrixFlags)flags);
|
||
|
}
|
||
|
|
||
|
static jboolean getSegment(JNIEnv* env, jobject clazz, PathMeasurePair* pair, jfloat startF,
|
||
|
jfloat stopF, SkPath* dst, jboolean startWithMoveTo) {
|
||
|
return pair->fMeasure.getSegment(SkFloatToScalar(startF), SkFloatToScalar(stopF), dst, startWithMoveTo);
|
||
|
}
|
||
|
|
||
|
static jboolean isClosed(JNIEnv* env, jobject clazz, PathMeasurePair* pair) {
|
||
|
return pair->fMeasure.isClosed();
|
||
|
}
|
||
|
|
||
|
static jboolean nextContour(JNIEnv* env, jobject clazz, PathMeasurePair* pair) {
|
||
|
return pair->fMeasure.nextContour();
|
||
|
}
|
||
|
|
||
|
static void destroy(JNIEnv* env, jobject clazz, PathMeasurePair* pair) {
|
||
|
delete pair;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
static JNINativeMethod methods[] = {
|
||
|
{"native_create", "(IZ)I", (void*) SkPathMeasureGlue::create },
|
||
|
{"native_setPath", "(IIZ)V", (void*) SkPathMeasureGlue::setPath },
|
||
|
{"native_getLength", "(I)F", (void*) SkPathMeasureGlue::getLength },
|
||
|
{"native_getPosTan", "(IF[F[F)Z", (void*) SkPathMeasureGlue::getPosTan },
|
||
|
{"native_getMatrix", "(IFII)Z", (void*) SkPathMeasureGlue::getMatrix },
|
||
|
{"native_getSegment", "(IFFIZ)Z", (void*) SkPathMeasureGlue::getSegment },
|
||
|
{"native_isClosed", "(I)Z", (void*) SkPathMeasureGlue::isClosed },
|
||
|
{"native_nextContour", "(I)Z", (void*) SkPathMeasureGlue::nextContour },
|
||
|
{"native_destroy", "(I)V", (void*) SkPathMeasureGlue::destroy }
|
||
|
};
|
||
|
|
||
|
int register_android_graphics_PathMeasure(JNIEnv* env) {
|
||
|
int result = AndroidRuntime::registerNativeMethods(env, "android/graphics/PathMeasure", methods,
|
||
|
sizeof(methods) / sizeof(methods[0]));
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
}
|