blob: 461f7232b3b1b8a720a99c6102c83441c5b0a96f [file] [log] [blame]
Leon Scroggins IIIca320212013-08-20 17:59:39 -04001#include "ScopedLocalRef.h"
Leon Scroggins III7315f1b2013-09-10 20:26:05 -04002#include "SkFrontBufferedStream.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003#include "SkMovie.h"
4#include "SkStream.h"
5#include "GraphicsJNI.h"
6#include "SkTemplates.h"
7#include "SkUtils.h"
Leon Scroggins IIIca320212013-08-20 17:59:39 -04008#include "Utils.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009#include "CreateJavaOutputStreamAdaptor.h"
10
Mathias Agopianb13b9bd2012-02-17 18:27:36 -080011#include <androidfw/Asset.h>
12#include <androidfw/ResourceTypes.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013#include <netinet/in.h>
14
15#if 0
16 #define TRACE_BITMAP(code) code
17#else
18 #define TRACE_BITMAP(code)
19#endif
20
21static jclass gMovie_class;
22static jmethodID gMovie_constructorMethodID;
23static jfieldID gMovie_nativeInstanceID;
24
25jobject create_jmovie(JNIEnv* env, SkMovie* moov) {
26 if (NULL == moov) {
27 return NULL;
28 }
Elliott Hughescf6f7a02011-04-12 17:50:45 -070029 return env->NewObject(gMovie_class, gMovie_constructorMethodID,
Ashok Bhatdcaf5592014-01-08 16:47:08 +000030 static_cast<jlong>(reinterpret_cast<uintptr_t>(moov)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031}
32
33static SkMovie* J2Movie(JNIEnv* env, jobject movie) {
34 SkASSERT(env);
35 SkASSERT(movie);
36 SkASSERT(env->IsInstanceOf(movie, gMovie_class));
Ashok Bhatdcaf5592014-01-08 16:47:08 +000037 SkMovie* m = (SkMovie*)env->GetLongField(movie, gMovie_nativeInstanceID);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038 SkASSERT(m);
39 return m;
40}
41
42///////////////////////////////////////////////////////////////////////////////
43
Ashok Bhatdcaf5592014-01-08 16:47:08 +000044static jint movie_width(JNIEnv* env, jobject movie) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045 NPE_CHECK_RETURN_ZERO(env, movie);
Ashok Bhatdcaf5592014-01-08 16:47:08 +000046 return static_cast<jint>(J2Movie(env, movie)->width());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047}
48
Ashok Bhatdcaf5592014-01-08 16:47:08 +000049static jint movie_height(JNIEnv* env, jobject movie) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050 NPE_CHECK_RETURN_ZERO(env, movie);
Ashok Bhatdcaf5592014-01-08 16:47:08 +000051 return static_cast<jint>(J2Movie(env, movie)->height());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052}
53
54static jboolean movie_isOpaque(JNIEnv* env, jobject movie) {
55 NPE_CHECK_RETURN_ZERO(env, movie);
Ashok Bhatdcaf5592014-01-08 16:47:08 +000056 return J2Movie(env, movie)->isOpaque() ? JNI_TRUE : JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057}
58
Ashok Bhatdcaf5592014-01-08 16:47:08 +000059static jint movie_duration(JNIEnv* env, jobject movie) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060 NPE_CHECK_RETURN_ZERO(env, movie);
Ashok Bhatdcaf5592014-01-08 16:47:08 +000061 return static_cast<jint>(J2Movie(env, movie)->duration());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080062}
63
Ashok Bhatdcaf5592014-01-08 16:47:08 +000064static jboolean movie_setTime(JNIEnv* env, jobject movie, jint ms) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065 NPE_CHECK_RETURN_ZERO(env, movie);
Ashok Bhatdcaf5592014-01-08 16:47:08 +000066 return J2Movie(env, movie)->setTime(ms) ? JNI_TRUE : JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067}
68
69static void movie_draw(JNIEnv* env, jobject movie, jobject canvas,
70 jfloat fx, jfloat fy, jobject jpaint) {
71 NPE_CHECK_RETURN_VOID(env, movie);
72 NPE_CHECK_RETURN_VOID(env, canvas);
73 // its OK for paint to be null
74
75 SkMovie* m = J2Movie(env, movie);
76 SkCanvas* c = GraphicsJNI::getNativeCanvas(env, canvas);
77 SkScalar sx = SkFloatToScalar(fx);
78 SkScalar sy = SkFloatToScalar(fy);
79 const SkBitmap& b = m->bitmap();
80 const SkPaint* p = jpaint ? GraphicsJNI::getNativePaint(env, jpaint) : NULL;
81
82 c->drawBitmap(b, sx, sy, p);
83}
84
Ashok Bhatdcaf5592014-01-08 16:47:08 +000085static jobject movie_decodeAsset(JNIEnv* env, jobject clazz, jlong native_asset) {
Leon Scroggins III7315f1b2013-09-10 20:26:05 -040086 android::Asset* asset = reinterpret_cast<android::Asset*>(native_asset);
87 if (asset == NULL) return NULL;
Leon Scroggins IIIb9c58ab2013-12-03 15:10:04 -050088 SkAutoTUnref<SkStreamRewindable> stream (new android::AssetStreamAdaptor(asset,
89 android::AssetStreamAdaptor::kNo_OwnAsset,
90 android::AssetStreamAdaptor::kNo_HasMemoryBase));
Leon Scroggins III7315f1b2013-09-10 20:26:05 -040091 SkMovie* moov = SkMovie::DecodeStream(stream.get());
92 return create_jmovie(env, moov);
93}
94
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095static jobject movie_decodeStream(JNIEnv* env, jobject clazz, jobject istream) {
Elliott Hughes8451b252011-04-07 19:17:57 -070096
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097 NPE_CHECK_RETURN_ZERO(env, istream);
98
Leon Scroggins III7315f1b2013-09-10 20:26:05 -040099 jbyteArray byteArray = env->NewByteArray(16*1024);
100 ScopedLocalRef<jbyteArray> scoper(env, byteArray);
101 SkStream* strm = CreateJavaInputStreamAdaptor(env, istream, byteArray);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102 if (NULL == strm) {
103 return 0;
104 }
105
Leon Scroggins III7315f1b2013-09-10 20:26:05 -0400106 // Need to buffer enough input to be able to rewind as much as might be read by a decoder
107 // trying to determine the stream's format. The only decoder for movies is GIF, which
108 // will only read 6.
109 // FIXME: Get this number from SkImageDecoder
110 SkAutoTUnref<SkStreamRewindable> bufferedStream(SkFrontBufferedStream::Create(strm, 6));
111 SkASSERT(bufferedStream.get() != NULL);
112
113 SkMovie* moov = SkMovie::DecodeStream(bufferedStream);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114 strm->unref();
115 return create_jmovie(env, moov);
116}
117
118static jobject movie_decodeByteArray(JNIEnv* env, jobject clazz,
119 jbyteArray byteArray,
Ashok Bhatdcaf5592014-01-08 16:47:08 +0000120 jint offset, jint length) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700121
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800122 NPE_CHECK_RETURN_ZERO(env, byteArray);
123
124 int totalLength = env->GetArrayLength(byteArray);
125 if ((offset | length) < 0 || offset + length > totalLength) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700126 doThrowAIOOBE(env);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800127 return 0;
128 }
129
130 AutoJavaByteArray ar(env, byteArray);
131 SkMovie* moov = SkMovie::DecodeMemory(ar.ptr() + offset, length);
132 return create_jmovie(env, moov);
133}
134
Ashok Bhatdcaf5592014-01-08 16:47:08 +0000135static void movie_destructor(JNIEnv* env, jobject, jlong movieHandle) {
136 SkMovie* movie = (SkMovie*) movieHandle;
Kimiyoshi Kusaka08d77782011-03-28 11:58:51 +0900137 delete movie;
138}
139
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140//////////////////////////////////////////////////////////////////////////////////////////////
141
142#include <android_runtime/AndroidRuntime.h>
143
144static JNINativeMethod gMethods[] = {
145 { "width", "()I", (void*)movie_width },
146 { "height", "()I", (void*)movie_height },
147 { "isOpaque", "()Z", (void*)movie_isOpaque },
148 { "duration", "()I", (void*)movie_duration },
149 { "setTime", "(I)Z", (void*)movie_setTime },
150 { "draw", "(Landroid/graphics/Canvas;FFLandroid/graphics/Paint;)V",
151 (void*)movie_draw },
Ashok Bhatdcaf5592014-01-08 16:47:08 +0000152 { "nativeDecodeAsset", "(J)Landroid/graphics/Movie;",
Leon Scroggins III7315f1b2013-09-10 20:26:05 -0400153 (void*)movie_decodeAsset },
154 { "nativeDecodeStream", "(Ljava/io/InputStream;)Landroid/graphics/Movie;",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155 (void*)movie_decodeStream },
Ashok Bhatdcaf5592014-01-08 16:47:08 +0000156 { "nativeDestructor","(J)V", (void*)movie_destructor },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800157 { "decodeByteArray", "([BII)Landroid/graphics/Movie;",
158 (void*)movie_decodeByteArray },
159};
160
161#define kClassPathName "android/graphics/Movie"
162
163#define RETURN_ERR_IF_NULL(value) do { if (!(value)) { assert(0); return -1; } } while (false)
164
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800165int register_android_graphics_Movie(JNIEnv* env)
166{
167 gMovie_class = env->FindClass(kClassPathName);
168 RETURN_ERR_IF_NULL(gMovie_class);
169 gMovie_class = (jclass)env->NewGlobalRef(gMovie_class);
Elliott Hughes8451b252011-04-07 19:17:57 -0700170
Ashok Bhatdcaf5592014-01-08 16:47:08 +0000171 gMovie_constructorMethodID = env->GetMethodID(gMovie_class, "<init>", "(J)V");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800172 RETURN_ERR_IF_NULL(gMovie_constructorMethodID);
173
Ashok Bhatdcaf5592014-01-08 16:47:08 +0000174 gMovie_nativeInstanceID = env->GetFieldID(gMovie_class, "mNativeMovie", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800175 RETURN_ERR_IF_NULL(gMovie_nativeInstanceID);
176
177 return android::AndroidRuntime::registerNativeMethods(env, kClassPathName,
178 gMethods, SK_ARRAY_COUNT(gMethods));
179}