1#include "GraphicsJNI.h"
2#include "SkInterpolator.h"
3#include "core_jni_helpers.h"
4
5#include <jni.h>
6
7static jlong Interpolator_constructor(JNIEnv* env, jobject clazz, jint valueCount, jint frameCount)
8{
9    return reinterpret_cast<jlong>(new SkInterpolator(valueCount, frameCount));
10}
11
12static void Interpolator_destructor(JNIEnv* env, jobject clazz, jlong interpHandle)
13{
14    SkInterpolator* interp = reinterpret_cast<SkInterpolator*>(interpHandle);
15    delete interp;
16}
17
18static void Interpolator_reset(JNIEnv* env, jobject clazz, jlong interpHandle, jint valueCount, jint frameCount)
19{
20    SkInterpolator* interp = reinterpret_cast<SkInterpolator*>(interpHandle);
21    interp->reset(valueCount, frameCount);
22}
23
24static void Interpolator_setKeyFrame(JNIEnv* env, jobject clazz, jlong interpHandle, jint index, jint msec, jfloatArray valueArray, jfloatArray blendArray)
25{
26    SkInterpolator* interp = reinterpret_cast<SkInterpolator*>(interpHandle);
27
28    AutoJavaFloatArray autoValues(env, valueArray);
29    AutoJavaFloatArray autoBlend(env, blendArray, 4);
30#ifdef SK_SCALAR_IS_FLOAT
31    SkScalar* scalars = autoValues.ptr();
32    SkScalar* blend = autoBlend.ptr();
33#else
34    #error Need to convert float array to SkScalar array before calling the following function.
35#endif
36
37    interp->setKeyFrame(index, msec, scalars, blend);
38}
39
40static void Interpolator_setRepeatMirror(JNIEnv* env, jobject clazz, jlong interpHandle, jfloat repeatCount, jboolean mirror)
41{
42    SkInterpolator* interp = reinterpret_cast<SkInterpolator*>(interpHandle);
43    if (repeatCount > 32000)
44        repeatCount = 32000;
45
46    interp->setRepeatCount(repeatCount);
47    interp->setMirror(mirror != 0);
48}
49
50static jint Interpolator_timeToValues(JNIEnv* env, jobject clazz, jlong interpHandle, jint msec, jfloatArray valueArray)
51{
52    SkInterpolator* interp = reinterpret_cast<SkInterpolator*>(interpHandle);
53    SkInterpolatorBase::Result result;
54
55    float* values = valueArray ? env->GetFloatArrayElements(valueArray, NULL) : NULL;
56    result = interp->timeToValues(msec, (SkScalar*)values);
57
58    if (valueArray) {
59        int n = env->GetArrayLength(valueArray);
60        for (int i = 0; i < n; i++) {
61            values[i] = SkScalarToFloat(*(SkScalar*)&values[i]);
62        }
63        env->ReleaseFloatArrayElements(valueArray, values, 0);
64    }
65
66    return static_cast<jint>(result);
67}
68
69// ----------------------------------------------------------------------------
70
71/*
72 * JNI registration.
73 */
74static const JNINativeMethod gInterpolatorMethods[] = {
75    { "nativeConstructor",      "(II)J",        (void*)Interpolator_constructor     },
76    { "nativeDestructor",       "(J)V",         (void*)Interpolator_destructor      },
77    { "nativeReset",            "(JII)V",       (void*)Interpolator_reset           },
78    { "nativeSetKeyFrame",      "(JII[F[F)V",   (void*)Interpolator_setKeyFrame     },
79    { "nativeSetRepeatMirror",  "(JFZ)V",       (void*)Interpolator_setRepeatMirror },
80    { "nativeTimeToValues",     "(JI[F)I",      (void*)Interpolator_timeToValues    }
81};
82
83int register_android_graphics_Interpolator(JNIEnv* env)
84{
85    return android::RegisterMethodsOrDie(env, "android/graphics/Interpolator",
86                                         gInterpolatorMethods, NELEM(gInterpolatorMethods));
87}
88