1*d57664e9SAndroid Build Coastguard Worker /*
2*d57664e9SAndroid Build Coastguard Worker * Copyright (C) 2018 The Android Open Source Project
3*d57664e9SAndroid Build Coastguard Worker *
4*d57664e9SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*d57664e9SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*d57664e9SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*d57664e9SAndroid Build Coastguard Worker *
8*d57664e9SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*d57664e9SAndroid Build Coastguard Worker *
10*d57664e9SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*d57664e9SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*d57664e9SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*d57664e9SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*d57664e9SAndroid Build Coastguard Worker * limitations under the License.
15*d57664e9SAndroid Build Coastguard Worker */
16*d57664e9SAndroid Build Coastguard Worker
17*d57664e9SAndroid Build Coastguard Worker #include <SkAndroidCodec.h>
18*d57664e9SAndroid Build Coastguard Worker #include <SkAnimatedImage.h>
19*d57664e9SAndroid Build Coastguard Worker #include <SkColorFilter.h>
20*d57664e9SAndroid Build Coastguard Worker #include <SkEncodedImageFormat.h>
21*d57664e9SAndroid Build Coastguard Worker #include <SkPicture.h>
22*d57664e9SAndroid Build Coastguard Worker #include <SkPictureRecorder.h>
23*d57664e9SAndroid Build Coastguard Worker #include <SkRect.h>
24*d57664e9SAndroid Build Coastguard Worker #include <SkRefCnt.h>
25*d57664e9SAndroid Build Coastguard Worker #include <hwui/AnimatedImageDrawable.h>
26*d57664e9SAndroid Build Coastguard Worker #include <hwui/Canvas.h>
27*d57664e9SAndroid Build Coastguard Worker #include <hwui/ImageDecoder.h>
28*d57664e9SAndroid Build Coastguard Worker #ifdef __ANDROID__
29*d57664e9SAndroid Build Coastguard Worker #include <utils/Looper.h>
30*d57664e9SAndroid Build Coastguard Worker #else
31*d57664e9SAndroid Build Coastguard Worker #include "utils/MessageHandler.h"
32*d57664e9SAndroid Build Coastguard Worker #endif
33*d57664e9SAndroid Build Coastguard Worker
34*d57664e9SAndroid Build Coastguard Worker #include "ColorFilter.h"
35*d57664e9SAndroid Build Coastguard Worker #include "GraphicsJNI.h"
36*d57664e9SAndroid Build Coastguard Worker #include "ImageDecoder.h"
37*d57664e9SAndroid Build Coastguard Worker #include "Utils.h"
38*d57664e9SAndroid Build Coastguard Worker
39*d57664e9SAndroid Build Coastguard Worker using namespace android;
40*d57664e9SAndroid Build Coastguard Worker
41*d57664e9SAndroid Build Coastguard Worker static jclass gAnimatedImageDrawableClass;
42*d57664e9SAndroid Build Coastguard Worker static jmethodID gAnimatedImageDrawable_callOnAnimationEndMethodID;
43*d57664e9SAndroid Build Coastguard Worker
44*d57664e9SAndroid Build Coastguard Worker // Note: jpostProcess holds a handle to the ImageDecoder.
AnimatedImageDrawable_nCreate(JNIEnv * env,jobject,jlong nativeImageDecoder,jobject jpostProcess,jint width,jint height,jlong colorSpaceHandle,jboolean extended,jobject jsubset)45*d57664e9SAndroid Build Coastguard Worker static jlong AnimatedImageDrawable_nCreate(JNIEnv* env, jobject /*clazz*/,
46*d57664e9SAndroid Build Coastguard Worker jlong nativeImageDecoder, jobject jpostProcess,
47*d57664e9SAndroid Build Coastguard Worker jint width, jint height, jlong colorSpaceHandle,
48*d57664e9SAndroid Build Coastguard Worker jboolean extended, jobject jsubset) {
49*d57664e9SAndroid Build Coastguard Worker if (nativeImageDecoder == 0) {
50*d57664e9SAndroid Build Coastguard Worker doThrowIOE(env, "Cannot create AnimatedImageDrawable from null!");
51*d57664e9SAndroid Build Coastguard Worker return 0;
52*d57664e9SAndroid Build Coastguard Worker }
53*d57664e9SAndroid Build Coastguard Worker
54*d57664e9SAndroid Build Coastguard Worker auto* imageDecoder = reinterpret_cast<ImageDecoder*>(nativeImageDecoder);
55*d57664e9SAndroid Build Coastguard Worker SkIRect subset;
56*d57664e9SAndroid Build Coastguard Worker if (jsubset) {
57*d57664e9SAndroid Build Coastguard Worker GraphicsJNI::jrect_to_irect(env, jsubset, &subset);
58*d57664e9SAndroid Build Coastguard Worker } else {
59*d57664e9SAndroid Build Coastguard Worker subset = SkIRect::MakeWH(width, height);
60*d57664e9SAndroid Build Coastguard Worker }
61*d57664e9SAndroid Build Coastguard Worker
62*d57664e9SAndroid Build Coastguard Worker bool hasRestoreFrame = false;
63*d57664e9SAndroid Build Coastguard Worker if (imageDecoder->mCodec->getEncodedFormat() != SkEncodedImageFormat::kWEBP) {
64*d57664e9SAndroid Build Coastguard Worker const int frameCount = imageDecoder->mCodec->codec()->getFrameCount();
65*d57664e9SAndroid Build Coastguard Worker for (int i = 0; i < frameCount; ++i) {
66*d57664e9SAndroid Build Coastguard Worker SkCodec::FrameInfo frameInfo;
67*d57664e9SAndroid Build Coastguard Worker if (!imageDecoder->mCodec->codec()->getFrameInfo(i, &frameInfo)) {
68*d57664e9SAndroid Build Coastguard Worker doThrowIOE(env, "Failed to read frame info!");
69*d57664e9SAndroid Build Coastguard Worker return 0;
70*d57664e9SAndroid Build Coastguard Worker }
71*d57664e9SAndroid Build Coastguard Worker if (frameInfo.fDisposalMethod == SkCodecAnimation::DisposalMethod::kRestorePrevious) {
72*d57664e9SAndroid Build Coastguard Worker hasRestoreFrame = true;
73*d57664e9SAndroid Build Coastguard Worker break;
74*d57664e9SAndroid Build Coastguard Worker }
75*d57664e9SAndroid Build Coastguard Worker }
76*d57664e9SAndroid Build Coastguard Worker }
77*d57664e9SAndroid Build Coastguard Worker
78*d57664e9SAndroid Build Coastguard Worker auto info = imageDecoder->mCodec->getInfo().makeWH(width, height)
79*d57664e9SAndroid Build Coastguard Worker .makeColorSpace(GraphicsJNI::getNativeColorSpace(colorSpaceHandle));
80*d57664e9SAndroid Build Coastguard Worker if (extended) {
81*d57664e9SAndroid Build Coastguard Worker info = info.makeColorType(kRGBA_F16_SkColorType);
82*d57664e9SAndroid Build Coastguard Worker }
83*d57664e9SAndroid Build Coastguard Worker
84*d57664e9SAndroid Build Coastguard Worker size_t bytesUsed = info.computeMinByteSize();
85*d57664e9SAndroid Build Coastguard Worker // SkAnimatedImage has one SkBitmap for decoding, plus an extra one if there is a
86*d57664e9SAndroid Build Coastguard Worker // kRestorePrevious frame. AnimatedImageDrawable has two SkPictures storing the current
87*d57664e9SAndroid Build Coastguard Worker // frame and the next frame. (The former assumes that the image is animated, and the
88*d57664e9SAndroid Build Coastguard Worker // latter assumes that it is drawn to a hardware canvas.)
89*d57664e9SAndroid Build Coastguard Worker bytesUsed *= hasRestoreFrame ? 4 : 3;
90*d57664e9SAndroid Build Coastguard Worker sk_sp<SkPicture> picture;
91*d57664e9SAndroid Build Coastguard Worker if (jpostProcess) {
92*d57664e9SAndroid Build Coastguard Worker SkRect bounds = SkRect::MakeWH(subset.width(), subset.height());
93*d57664e9SAndroid Build Coastguard Worker
94*d57664e9SAndroid Build Coastguard Worker SkPictureRecorder recorder;
95*d57664e9SAndroid Build Coastguard Worker SkCanvas* skcanvas = recorder.beginRecording(bounds);
96*d57664e9SAndroid Build Coastguard Worker std::unique_ptr<Canvas> canvas(Canvas::create_canvas(skcanvas));
97*d57664e9SAndroid Build Coastguard Worker postProcessAndRelease(env, jpostProcess, std::move(canvas));
98*d57664e9SAndroid Build Coastguard Worker if (env->ExceptionCheck()) {
99*d57664e9SAndroid Build Coastguard Worker return 0;
100*d57664e9SAndroid Build Coastguard Worker }
101*d57664e9SAndroid Build Coastguard Worker picture = recorder.finishRecordingAsPicture();
102*d57664e9SAndroid Build Coastguard Worker bytesUsed += picture->approximateBytesUsed();
103*d57664e9SAndroid Build Coastguard Worker }
104*d57664e9SAndroid Build Coastguard Worker
105*d57664e9SAndroid Build Coastguard Worker SkEncodedImageFormat format = imageDecoder->mCodec->getEncodedFormat();
106*d57664e9SAndroid Build Coastguard Worker sk_sp<SkAnimatedImage> animatedImg = SkAnimatedImage::Make(std::move(imageDecoder->mCodec),
107*d57664e9SAndroid Build Coastguard Worker info, subset,
108*d57664e9SAndroid Build Coastguard Worker std::move(picture));
109*d57664e9SAndroid Build Coastguard Worker if (!animatedImg) {
110*d57664e9SAndroid Build Coastguard Worker doThrowIOE(env, "Failed to create drawable");
111*d57664e9SAndroid Build Coastguard Worker return 0;
112*d57664e9SAndroid Build Coastguard Worker }
113*d57664e9SAndroid Build Coastguard Worker
114*d57664e9SAndroid Build Coastguard Worker bytesUsed += sizeof(animatedImg.get());
115*d57664e9SAndroid Build Coastguard Worker
116*d57664e9SAndroid Build Coastguard Worker sk_sp<AnimatedImageDrawable> drawable(
117*d57664e9SAndroid Build Coastguard Worker new AnimatedImageDrawable(std::move(animatedImg), bytesUsed, format));
118*d57664e9SAndroid Build Coastguard Worker return reinterpret_cast<jlong>(drawable.release());
119*d57664e9SAndroid Build Coastguard Worker }
120*d57664e9SAndroid Build Coastguard Worker
AnimatedImageDrawable_destruct(AnimatedImageDrawable * drawable)121*d57664e9SAndroid Build Coastguard Worker static void AnimatedImageDrawable_destruct(AnimatedImageDrawable* drawable) {
122*d57664e9SAndroid Build Coastguard Worker SkSafeUnref(drawable);
123*d57664e9SAndroid Build Coastguard Worker }
124*d57664e9SAndroid Build Coastguard Worker
AnimatedImageDrawable_nGetNativeFinalizer(JNIEnv *,jobject)125*d57664e9SAndroid Build Coastguard Worker static jlong AnimatedImageDrawable_nGetNativeFinalizer(JNIEnv* /*env*/, jobject /*clazz*/) {
126*d57664e9SAndroid Build Coastguard Worker return static_cast<jlong>(reinterpret_cast<uintptr_t>(&AnimatedImageDrawable_destruct));
127*d57664e9SAndroid Build Coastguard Worker }
128*d57664e9SAndroid Build Coastguard Worker
129*d57664e9SAndroid Build Coastguard Worker // Java's FINISHED relies on this being -1
130*d57664e9SAndroid Build Coastguard Worker static_assert(SkAnimatedImage::kFinished == -1);
131*d57664e9SAndroid Build Coastguard Worker
AnimatedImageDrawable_nDraw(JNIEnv * env,jobject,jlong nativePtr,jlong canvasPtr)132*d57664e9SAndroid Build Coastguard Worker static jlong AnimatedImageDrawable_nDraw(JNIEnv* env, jobject /*clazz*/, jlong nativePtr,
133*d57664e9SAndroid Build Coastguard Worker jlong canvasPtr) {
134*d57664e9SAndroid Build Coastguard Worker auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr);
135*d57664e9SAndroid Build Coastguard Worker auto* canvas = reinterpret_cast<Canvas*>(canvasPtr);
136*d57664e9SAndroid Build Coastguard Worker return (jlong) canvas->drawAnimatedImage(drawable);
137*d57664e9SAndroid Build Coastguard Worker }
138*d57664e9SAndroid Build Coastguard Worker
AnimatedImageDrawable_nSetAlpha(JNIEnv * env,jobject,jlong nativePtr,jint alpha)139*d57664e9SAndroid Build Coastguard Worker static void AnimatedImageDrawable_nSetAlpha(JNIEnv* env, jobject /*clazz*/, jlong nativePtr,
140*d57664e9SAndroid Build Coastguard Worker jint alpha) {
141*d57664e9SAndroid Build Coastguard Worker auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr);
142*d57664e9SAndroid Build Coastguard Worker drawable->setStagingAlpha(alpha);
143*d57664e9SAndroid Build Coastguard Worker }
144*d57664e9SAndroid Build Coastguard Worker
AnimatedImageDrawable_nGetAlpha(JNIEnv * env,jobject,jlong nativePtr)145*d57664e9SAndroid Build Coastguard Worker static jlong AnimatedImageDrawable_nGetAlpha(JNIEnv* env, jobject /*clazz*/, jlong nativePtr) {
146*d57664e9SAndroid Build Coastguard Worker auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr);
147*d57664e9SAndroid Build Coastguard Worker return drawable->getStagingAlpha();
148*d57664e9SAndroid Build Coastguard Worker }
149*d57664e9SAndroid Build Coastguard Worker
AnimatedImageDrawable_nSetColorFilter(JNIEnv * env,jobject,jlong nativePtr,jlong nativeFilter)150*d57664e9SAndroid Build Coastguard Worker static void AnimatedImageDrawable_nSetColorFilter(JNIEnv* env, jobject /*clazz*/, jlong nativePtr,
151*d57664e9SAndroid Build Coastguard Worker jlong nativeFilter) {
152*d57664e9SAndroid Build Coastguard Worker auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr);
153*d57664e9SAndroid Build Coastguard Worker auto filter = uirenderer::ColorFilter::fromJava(nativeFilter);
154*d57664e9SAndroid Build Coastguard Worker auto skColorFilter = filter != nullptr ? filter->getInstance() : sk_sp<SkColorFilter>();
155*d57664e9SAndroid Build Coastguard Worker drawable->setStagingColorFilter(skColorFilter);
156*d57664e9SAndroid Build Coastguard Worker }
157*d57664e9SAndroid Build Coastguard Worker
AnimatedImageDrawable_nIsRunning(JNIEnv * env,jobject,jlong nativePtr)158*d57664e9SAndroid Build Coastguard Worker static jboolean AnimatedImageDrawable_nIsRunning(JNIEnv* env, jobject /*clazz*/, jlong nativePtr) {
159*d57664e9SAndroid Build Coastguard Worker auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr);
160*d57664e9SAndroid Build Coastguard Worker return drawable->isRunning();
161*d57664e9SAndroid Build Coastguard Worker }
162*d57664e9SAndroid Build Coastguard Worker
AnimatedImageDrawable_nStart(JNIEnv * env,jobject,jlong nativePtr)163*d57664e9SAndroid Build Coastguard Worker static jboolean AnimatedImageDrawable_nStart(JNIEnv* env, jobject /*clazz*/, jlong nativePtr) {
164*d57664e9SAndroid Build Coastguard Worker auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr);
165*d57664e9SAndroid Build Coastguard Worker return drawable->start();
166*d57664e9SAndroid Build Coastguard Worker }
167*d57664e9SAndroid Build Coastguard Worker
AnimatedImageDrawable_nStop(JNIEnv * env,jobject,jlong nativePtr)168*d57664e9SAndroid Build Coastguard Worker static jboolean AnimatedImageDrawable_nStop(JNIEnv* env, jobject /*clazz*/, jlong nativePtr) {
169*d57664e9SAndroid Build Coastguard Worker auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr);
170*d57664e9SAndroid Build Coastguard Worker return drawable->stop();
171*d57664e9SAndroid Build Coastguard Worker }
172*d57664e9SAndroid Build Coastguard Worker
173*d57664e9SAndroid Build Coastguard Worker // Java's LOOP_INFINITE relies on this being the same.
174*d57664e9SAndroid Build Coastguard Worker static_assert(SkCodec::kRepetitionCountInfinite == -1);
175*d57664e9SAndroid Build Coastguard Worker
AnimatedImageDrawable_nGetRepeatCount(JNIEnv * env,jobject,jlong nativePtr)176*d57664e9SAndroid Build Coastguard Worker static jint AnimatedImageDrawable_nGetRepeatCount(JNIEnv* env, jobject /*clazz*/, jlong nativePtr) {
177*d57664e9SAndroid Build Coastguard Worker auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr);
178*d57664e9SAndroid Build Coastguard Worker return drawable->getRepetitionCount();
179*d57664e9SAndroid Build Coastguard Worker }
180*d57664e9SAndroid Build Coastguard Worker
AnimatedImageDrawable_nSetRepeatCount(JNIEnv * env,jobject,jlong nativePtr,jint loopCount)181*d57664e9SAndroid Build Coastguard Worker static void AnimatedImageDrawable_nSetRepeatCount(JNIEnv* env, jobject /*clazz*/, jlong nativePtr,
182*d57664e9SAndroid Build Coastguard Worker jint loopCount) {
183*d57664e9SAndroid Build Coastguard Worker auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr);
184*d57664e9SAndroid Build Coastguard Worker drawable->setRepetitionCount(loopCount);
185*d57664e9SAndroid Build Coastguard Worker }
186*d57664e9SAndroid Build Coastguard Worker
187*d57664e9SAndroid Build Coastguard Worker class InvokeListener : public MessageHandler {
188*d57664e9SAndroid Build Coastguard Worker public:
InvokeListener(JNIEnv * env,jobject javaObject)189*d57664e9SAndroid Build Coastguard Worker InvokeListener(JNIEnv* env, jobject javaObject) {
190*d57664e9SAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&mJvm) != JNI_OK);
191*d57664e9SAndroid Build Coastguard Worker mCallbackRef = env->NewGlobalRef(javaObject);
192*d57664e9SAndroid Build Coastguard Worker }
193*d57664e9SAndroid Build Coastguard Worker
~InvokeListener()194*d57664e9SAndroid Build Coastguard Worker ~InvokeListener() override {
195*d57664e9SAndroid Build Coastguard Worker auto* env = requireEnv(mJvm);
196*d57664e9SAndroid Build Coastguard Worker env->DeleteGlobalRef(mCallbackRef);
197*d57664e9SAndroid Build Coastguard Worker }
198*d57664e9SAndroid Build Coastguard Worker
handleMessage(const Message &)199*d57664e9SAndroid Build Coastguard Worker virtual void handleMessage(const Message&) override {
200*d57664e9SAndroid Build Coastguard Worker auto* env = get_env_or_die(mJvm);
201*d57664e9SAndroid Build Coastguard Worker env->CallStaticVoidMethod(gAnimatedImageDrawableClass,
202*d57664e9SAndroid Build Coastguard Worker gAnimatedImageDrawable_callOnAnimationEndMethodID, mCallbackRef);
203*d57664e9SAndroid Build Coastguard Worker }
204*d57664e9SAndroid Build Coastguard Worker
205*d57664e9SAndroid Build Coastguard Worker private:
206*d57664e9SAndroid Build Coastguard Worker JavaVM* mJvm;
207*d57664e9SAndroid Build Coastguard Worker jobject mCallbackRef;
208*d57664e9SAndroid Build Coastguard Worker };
209*d57664e9SAndroid Build Coastguard Worker
210*d57664e9SAndroid Build Coastguard Worker class JniAnimationEndListener : public OnAnimationEndListener {
211*d57664e9SAndroid Build Coastguard Worker #ifdef __ANDROID__
212*d57664e9SAndroid Build Coastguard Worker public:
JniAnimationEndListener(sp<Looper> && looper,JNIEnv * env,jobject javaObject)213*d57664e9SAndroid Build Coastguard Worker JniAnimationEndListener(sp<Looper>&& looper, JNIEnv* env, jobject javaObject) {
214*d57664e9SAndroid Build Coastguard Worker mListener = new InvokeListener(env, javaObject);
215*d57664e9SAndroid Build Coastguard Worker mLooper = std::move(looper);
216*d57664e9SAndroid Build Coastguard Worker }
217*d57664e9SAndroid Build Coastguard Worker
onAnimationEnd()218*d57664e9SAndroid Build Coastguard Worker void onAnimationEnd() override { mLooper->sendMessage(mListener, 0); }
219*d57664e9SAndroid Build Coastguard Worker
220*d57664e9SAndroid Build Coastguard Worker private:
221*d57664e9SAndroid Build Coastguard Worker sp<InvokeListener> mListener;
222*d57664e9SAndroid Build Coastguard Worker sp<Looper> mLooper;
223*d57664e9SAndroid Build Coastguard Worker #else
224*d57664e9SAndroid Build Coastguard Worker public:
225*d57664e9SAndroid Build Coastguard Worker JniAnimationEndListener(JNIEnv* env, jobject javaObject) {
226*d57664e9SAndroid Build Coastguard Worker mListener = new InvokeListener(env, javaObject);
227*d57664e9SAndroid Build Coastguard Worker }
228*d57664e9SAndroid Build Coastguard Worker
229*d57664e9SAndroid Build Coastguard Worker void onAnimationEnd() override { mListener->handleMessage(0); }
230*d57664e9SAndroid Build Coastguard Worker
231*d57664e9SAndroid Build Coastguard Worker private:
232*d57664e9SAndroid Build Coastguard Worker sp<InvokeListener> mListener;
233*d57664e9SAndroid Build Coastguard Worker #endif
234*d57664e9SAndroid Build Coastguard Worker };
235*d57664e9SAndroid Build Coastguard Worker
AnimatedImageDrawable_nSetOnAnimationEndListener(JNIEnv * env,jobject,jlong nativePtr,jobject jdrawable)236*d57664e9SAndroid Build Coastguard Worker static void AnimatedImageDrawable_nSetOnAnimationEndListener(JNIEnv* env, jobject /*clazz*/,
237*d57664e9SAndroid Build Coastguard Worker jlong nativePtr, jobject jdrawable) {
238*d57664e9SAndroid Build Coastguard Worker auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr);
239*d57664e9SAndroid Build Coastguard Worker if (!jdrawable) {
240*d57664e9SAndroid Build Coastguard Worker drawable->setOnAnimationEndListener(nullptr);
241*d57664e9SAndroid Build Coastguard Worker } else {
242*d57664e9SAndroid Build Coastguard Worker #ifdef __ANDROID__
243*d57664e9SAndroid Build Coastguard Worker sp<Looper> looper = Looper::getForThread();
244*d57664e9SAndroid Build Coastguard Worker if (!looper.get()) {
245*d57664e9SAndroid Build Coastguard Worker doThrowISE(env,
246*d57664e9SAndroid Build Coastguard Worker "Must set AnimatedImageDrawable's AnimationCallback on a thread with a "
247*d57664e9SAndroid Build Coastguard Worker "looper!");
248*d57664e9SAndroid Build Coastguard Worker return;
249*d57664e9SAndroid Build Coastguard Worker }
250*d57664e9SAndroid Build Coastguard Worker
251*d57664e9SAndroid Build Coastguard Worker drawable->setOnAnimationEndListener(
252*d57664e9SAndroid Build Coastguard Worker std::make_unique<JniAnimationEndListener>(std::move(looper), env, jdrawable));
253*d57664e9SAndroid Build Coastguard Worker #else
254*d57664e9SAndroid Build Coastguard Worker drawable->setOnAnimationEndListener(
255*d57664e9SAndroid Build Coastguard Worker std::make_unique<JniAnimationEndListener>(env, jdrawable));
256*d57664e9SAndroid Build Coastguard Worker #endif
257*d57664e9SAndroid Build Coastguard Worker }
258*d57664e9SAndroid Build Coastguard Worker }
259*d57664e9SAndroid Build Coastguard Worker
AnimatedImageDrawable_nNativeByteSize(JNIEnv * env,jobject,jlong nativePtr)260*d57664e9SAndroid Build Coastguard Worker static jlong AnimatedImageDrawable_nNativeByteSize(JNIEnv* env, jobject /*clazz*/, jlong nativePtr) {
261*d57664e9SAndroid Build Coastguard Worker auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr);
262*d57664e9SAndroid Build Coastguard Worker return drawable->byteSize();
263*d57664e9SAndroid Build Coastguard Worker }
264*d57664e9SAndroid Build Coastguard Worker
AnimatedImageDrawable_nSetMirrored(JNIEnv * env,jobject,jlong nativePtr,jboolean mirrored)265*d57664e9SAndroid Build Coastguard Worker static void AnimatedImageDrawable_nSetMirrored(JNIEnv* env, jobject /*clazz*/, jlong nativePtr,
266*d57664e9SAndroid Build Coastguard Worker jboolean mirrored) {
267*d57664e9SAndroid Build Coastguard Worker auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr);
268*d57664e9SAndroid Build Coastguard Worker drawable->setStagingMirrored(mirrored);
269*d57664e9SAndroid Build Coastguard Worker }
270*d57664e9SAndroid Build Coastguard Worker
AnimatedImageDrawable_nSetBounds(JNIEnv * env,jobject,jlong nativePtr,jobject jrect)271*d57664e9SAndroid Build Coastguard Worker static void AnimatedImageDrawable_nSetBounds(JNIEnv* env, jobject /*clazz*/, jlong nativePtr,
272*d57664e9SAndroid Build Coastguard Worker jobject jrect) {
273*d57664e9SAndroid Build Coastguard Worker auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr);
274*d57664e9SAndroid Build Coastguard Worker SkRect rect;
275*d57664e9SAndroid Build Coastguard Worker GraphicsJNI::jrect_to_rect(env, jrect, &rect);
276*d57664e9SAndroid Build Coastguard Worker drawable->setStagingBounds(rect);
277*d57664e9SAndroid Build Coastguard Worker }
278*d57664e9SAndroid Build Coastguard Worker
AnimatedImageDrawable_nSetFilterBitmap(JNIEnv * env,jobject,jlong nativePtr,jboolean filterBitmap)279*d57664e9SAndroid Build Coastguard Worker static jboolean AnimatedImageDrawable_nSetFilterBitmap(JNIEnv* env, jobject /*clazz*/,
280*d57664e9SAndroid Build Coastguard Worker jlong nativePtr, jboolean filterBitmap) {
281*d57664e9SAndroid Build Coastguard Worker auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr);
282*d57664e9SAndroid Build Coastguard Worker return drawable->setFilterBitmap(filterBitmap);
283*d57664e9SAndroid Build Coastguard Worker }
284*d57664e9SAndroid Build Coastguard Worker
AnimatedImageDrawable_nGetFilterBitmap(JNIEnv * env,jobject,jlong nativePtr)285*d57664e9SAndroid Build Coastguard Worker static jboolean AnimatedImageDrawable_nGetFilterBitmap(JNIEnv* env, jobject /*clazz*/,
286*d57664e9SAndroid Build Coastguard Worker jlong nativePtr) {
287*d57664e9SAndroid Build Coastguard Worker auto* drawable = reinterpret_cast<AnimatedImageDrawable*>(nativePtr);
288*d57664e9SAndroid Build Coastguard Worker return drawable->getFilterBitmap();
289*d57664e9SAndroid Build Coastguard Worker }
290*d57664e9SAndroid Build Coastguard Worker
291*d57664e9SAndroid Build Coastguard Worker static const JNINativeMethod gAnimatedImageDrawableMethods[] = {
292*d57664e9SAndroid Build Coastguard Worker {"nCreate", "(JLandroid/graphics/ImageDecoder;IIJZLandroid/graphics/Rect;)J",
293*d57664e9SAndroid Build Coastguard Worker (void*)AnimatedImageDrawable_nCreate},
294*d57664e9SAndroid Build Coastguard Worker {"nGetNativeFinalizer", "()J", (void*)AnimatedImageDrawable_nGetNativeFinalizer},
295*d57664e9SAndroid Build Coastguard Worker {"nDraw", "(JJ)J", (void*)AnimatedImageDrawable_nDraw},
296*d57664e9SAndroid Build Coastguard Worker {"nSetAlpha", "(JI)V", (void*)AnimatedImageDrawable_nSetAlpha},
297*d57664e9SAndroid Build Coastguard Worker {"nGetAlpha", "(J)I", (void*)AnimatedImageDrawable_nGetAlpha},
298*d57664e9SAndroid Build Coastguard Worker {"nSetColorFilter", "(JJ)V", (void*)AnimatedImageDrawable_nSetColorFilter},
299*d57664e9SAndroid Build Coastguard Worker {"nIsRunning", "(J)Z", (void*)AnimatedImageDrawable_nIsRunning},
300*d57664e9SAndroid Build Coastguard Worker {"nStart", "(J)Z", (void*)AnimatedImageDrawable_nStart},
301*d57664e9SAndroid Build Coastguard Worker {"nStop", "(J)Z", (void*)AnimatedImageDrawable_nStop},
302*d57664e9SAndroid Build Coastguard Worker {"nGetRepeatCount", "(J)I", (void*)AnimatedImageDrawable_nGetRepeatCount},
303*d57664e9SAndroid Build Coastguard Worker {"nSetRepeatCount", "(JI)V", (void*)AnimatedImageDrawable_nSetRepeatCount},
304*d57664e9SAndroid Build Coastguard Worker {"nSetOnAnimationEndListener", "(JLjava/lang/ref/WeakReference;)V",
305*d57664e9SAndroid Build Coastguard Worker (void*)AnimatedImageDrawable_nSetOnAnimationEndListener},
306*d57664e9SAndroid Build Coastguard Worker {"nNativeByteSize", "(J)J", (void*)AnimatedImageDrawable_nNativeByteSize},
307*d57664e9SAndroid Build Coastguard Worker {"nSetMirrored", "(JZ)V", (void*)AnimatedImageDrawable_nSetMirrored},
308*d57664e9SAndroid Build Coastguard Worker {"nSetBounds", "(JLandroid/graphics/Rect;)V", (void*)AnimatedImageDrawable_nSetBounds},
309*d57664e9SAndroid Build Coastguard Worker {"nSetFilterBitmap", "(JZ)Z", (void*)AnimatedImageDrawable_nSetFilterBitmap},
310*d57664e9SAndroid Build Coastguard Worker {"nGetFilterBitmap", "(J)Z", (void*)AnimatedImageDrawable_nGetFilterBitmap},
311*d57664e9SAndroid Build Coastguard Worker };
312*d57664e9SAndroid Build Coastguard Worker
register_android_graphics_drawable_AnimatedImageDrawable(JNIEnv * env)313*d57664e9SAndroid Build Coastguard Worker int register_android_graphics_drawable_AnimatedImageDrawable(JNIEnv* env) {
314*d57664e9SAndroid Build Coastguard Worker gAnimatedImageDrawableClass = reinterpret_cast<jclass>(env->NewGlobalRef(
315*d57664e9SAndroid Build Coastguard Worker FindClassOrDie(env, "android/graphics/drawable/AnimatedImageDrawable")));
316*d57664e9SAndroid Build Coastguard Worker gAnimatedImageDrawable_callOnAnimationEndMethodID =
317*d57664e9SAndroid Build Coastguard Worker GetStaticMethodIDOrDie(env, gAnimatedImageDrawableClass, "callOnAnimationEnd",
318*d57664e9SAndroid Build Coastguard Worker "(Ljava/lang/ref/WeakReference;)V");
319*d57664e9SAndroid Build Coastguard Worker
320*d57664e9SAndroid Build Coastguard Worker return android::RegisterMethodsOrDie(env, "android/graphics/drawable/AnimatedImageDrawable",
321*d57664e9SAndroid Build Coastguard Worker gAnimatedImageDrawableMethods, NELEM(gAnimatedImageDrawableMethods));
322*d57664e9SAndroid Build Coastguard Worker }
323*d57664e9SAndroid Build Coastguard Worker
324