/* * Copyright (C) 2016 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 "android/log.h" #include "GraphicsJNI.h" #include "Animator.h" #include "Interpolator.h" #include "PropertyValuesAnimatorSet.h" #include "PropertyValuesHolder.h" #include "VectorDrawable.h" namespace android { using namespace uirenderer; using namespace VectorDrawable; static struct { jclass clazz; jmethodID callOnFinished; } gVectorDrawableAnimatorClassInfo; static JNIEnv* getEnv(JavaVM* vm) { JNIEnv* env; if (vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) != JNI_OK) { return 0; } return env; } static AnimationListener* createAnimationListener(JNIEnv* env, jobject finishListener, jint id) { class AnimationListenerBridge : public AnimationListener { public: AnimationListenerBridge(JNIEnv* env, jobject finishListener, jint id) { mFinishListener = env->NewGlobalRef(finishListener); env->GetJavaVM(&mJvm); mId = id; } virtual ~AnimationListenerBridge() { if (mFinishListener) { onAnimationFinished(NULL); } } virtual void onAnimationFinished(BaseRenderNodeAnimator*) { LOG_ALWAYS_FATAL_IF(!mFinishListener, "Finished listener twice?"); JNIEnv* env = getEnv(mJvm); env->CallStaticVoidMethod( gVectorDrawableAnimatorClassInfo.clazz, gVectorDrawableAnimatorClassInfo.callOnFinished, mFinishListener, mId); releaseJavaObject(); } private: void releaseJavaObject() { JNIEnv* env = getEnv(mJvm); env->DeleteGlobalRef(mFinishListener); mFinishListener = NULL; } JavaVM* mJvm; jobject mFinishListener; jint mId; }; return new AnimationListenerBridge(env, finishListener, id); } static void addAnimator(JNIEnv*, jobject, jlong animatorSetPtr, jlong propertyHolderPtr, jlong interpolatorPtr, jlong startDelay, jlong duration, jint repeatCount, jint repeatMode) { PropertyValuesAnimatorSet* set = reinterpret_cast(animatorSetPtr); PropertyValuesHolder* holder = reinterpret_cast(propertyHolderPtr); Interpolator* interpolator = reinterpret_cast(interpolatorPtr); RepeatMode mode = static_cast(repeatMode); set->addPropertyAnimator(holder, interpolator, startDelay, duration, repeatCount, mode); } static jlong createAnimatorSet(JNIEnv*, jobject) { PropertyValuesAnimatorSet* animatorSet = new PropertyValuesAnimatorSet(); return reinterpret_cast(animatorSet); } static void setVectorDrawableTarget(JNIEnv*, jobject,jlong animatorPtr, jlong vectorDrawablePtr) { VectorDrawable::Tree* tree = reinterpret_cast(vectorDrawablePtr); PropertyValuesAnimatorSet* set = reinterpret_cast(animatorPtr); set->setVectorDrawable(tree); } static jlong createGroupPropertyHolder(JNIEnv*, jobject, jlong nativePtr, jint propertyId, jfloat startValue, jfloat endValue) { VectorDrawable::Group* group = reinterpret_cast(nativePtr); GroupPropertyValuesHolder* newHolder = new GroupPropertyValuesHolder(group, propertyId, startValue, endValue); return reinterpret_cast(newHolder); } static jlong createPathDataPropertyHolder(JNIEnv*, jobject, jlong nativePtr, jlong startValuePtr, jlong endValuePtr) { VectorDrawable::Path* path = reinterpret_cast(nativePtr); PathData* startData = reinterpret_cast(startValuePtr); PathData* endData = reinterpret_cast(endValuePtr); PathDataPropertyValuesHolder* newHolder = new PathDataPropertyValuesHolder(path, startData, endData); return reinterpret_cast(newHolder); } static jlong createPathColorPropertyHolder(JNIEnv*, jobject, jlong nativePtr, jint propertyId, int startValue, jint endValue) { VectorDrawable::FullPath* fullPath = reinterpret_cast(nativePtr); FullPathColorPropertyValuesHolder* newHolder = new FullPathColorPropertyValuesHolder(fullPath, propertyId, startValue, endValue); return reinterpret_cast(newHolder); } static jlong createPathPropertyHolder(JNIEnv*, jobject, jlong nativePtr, jint propertyId, float startValue, jfloat endValue) { VectorDrawable::FullPath* fullPath = reinterpret_cast(nativePtr); FullPathPropertyValuesHolder* newHolder = new FullPathPropertyValuesHolder(fullPath, propertyId, startValue, endValue); return reinterpret_cast(newHolder); } static jlong createRootAlphaPropertyHolder(JNIEnv*, jobject, jlong nativePtr, jfloat startValue, float endValue) { VectorDrawable::Tree* tree = reinterpret_cast(nativePtr); RootAlphaPropertyValuesHolder* newHolder = new RootAlphaPropertyValuesHolder(tree, startValue, endValue); return reinterpret_cast(newHolder); } static void setFloatPropertyHolderData(JNIEnv* env, jobject, jlong propertyHolderPtr, jfloatArray srcData, jint length) { jfloat* propertyData = env->GetFloatArrayElements(srcData, nullptr); PropertyValuesHolderImpl* holder = reinterpret_cast*>(propertyHolderPtr); holder->setPropertyDataSource(propertyData, length); env->ReleaseFloatArrayElements(srcData, propertyData, JNI_ABORT); } static void setIntPropertyHolderData(JNIEnv* env, jobject, jlong propertyHolderPtr, jintArray srcData, jint length) { jint* propertyData = env->GetIntArrayElements(srcData, nullptr); PropertyValuesHolderImpl* holder = reinterpret_cast*>(propertyHolderPtr); holder->setPropertyDataSource(propertyData, length); env->ReleaseIntArrayElements(srcData, propertyData, JNI_ABORT); } static void start(JNIEnv* env, jobject, jlong animatorSetPtr, jobject finishListener, jint id) { PropertyValuesAnimatorSet* set = reinterpret_cast(animatorSetPtr); AnimationListener* listener = createAnimationListener(env, finishListener, id); set->start(listener); } static void reverse(JNIEnv* env, jobject, jlong animatorSetPtr, jobject finishListener, jint id) { PropertyValuesAnimatorSet* set = reinterpret_cast(animatorSetPtr); AnimationListener* listener = createAnimationListener(env, finishListener, id); set->reverse(listener); } static void end(JNIEnv*, jobject, jlong animatorSetPtr) { PropertyValuesAnimatorSet* set = reinterpret_cast(animatorSetPtr); set->end(); } static void reset(JNIEnv*, jobject, jlong animatorSetPtr) { PropertyValuesAnimatorSet* set = reinterpret_cast(animatorSetPtr); set->reset(); } static const JNINativeMethod gMethods[] = { {"nCreateAnimatorSet", "()J", (void*)createAnimatorSet}, {"nSetVectorDrawableTarget", "(JJ)V", (void*)setVectorDrawableTarget}, {"nAddAnimator", "(JJJJJII)V", (void*)addAnimator}, {"nSetPropertyHolderData", "(J[FI)V", (void*)setFloatPropertyHolderData}, {"nSetPropertyHolderData", "(J[II)V", (void*)setIntPropertyHolderData}, {"nStart", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimatorRT;I)V", (void*)start}, {"nReverse", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimatorRT;I)V", (void*)reverse}, // ------------- @FastNative ------------------- {"nCreateGroupPropertyHolder", "(JIFF)J", (void*)createGroupPropertyHolder}, {"nCreatePathDataPropertyHolder", "(JJJ)J", (void*)createPathDataPropertyHolder}, {"nCreatePathColorPropertyHolder", "(JIII)J", (void*)createPathColorPropertyHolder}, {"nCreatePathPropertyHolder", "(JIFF)J", (void*)createPathPropertyHolder}, {"nCreateRootAlphaPropertyHolder", "(JFF)J", (void*)createRootAlphaPropertyHolder}, {"nEnd", "(J)V", (void*)end}, {"nReset", "(J)V", (void*)reset}, }; const char* const kClassPathName = "android/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimatorRT"; int register_android_graphics_drawable_AnimatedVectorDrawable(JNIEnv* env) { gVectorDrawableAnimatorClassInfo.clazz = FindClassOrDie(env, kClassPathName); gVectorDrawableAnimatorClassInfo.clazz = MakeGlobalRefOrDie(env, gVectorDrawableAnimatorClassInfo.clazz); gVectorDrawableAnimatorClassInfo.callOnFinished = GetStaticMethodIDOrDie( env, gVectorDrawableAnimatorClassInfo.clazz, "callOnFinished", "(Landroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimatorRT;I)V"); return RegisterMethodsOrDie(env, "android/graphics/drawable/AnimatedVectorDrawable", gMethods, NELEM(gMethods)); } }; // namespace android