1#include "SkMovie.h" 2#include "SkStream.h" 3#include "GraphicsJNI.h" 4#include "SkTemplates.h" 5#include "SkUtils.h" 6#include "CreateJavaOutputStreamAdaptor.h" 7 8#include <androidfw/Asset.h> 9#include <androidfw/ResourceTypes.h> 10#include <netinet/in.h> 11 12#if 0 13 #define TRACE_BITMAP(code) code 14#else 15 #define TRACE_BITMAP(code) 16#endif 17 18static jclass gMovie_class; 19static jmethodID gMovie_constructorMethodID; 20static jfieldID gMovie_nativeInstanceID; 21 22jobject create_jmovie(JNIEnv* env, SkMovie* moov) { 23 if (NULL == moov) { 24 return NULL; 25 } 26 return env->NewObject(gMovie_class, gMovie_constructorMethodID, 27 static_cast<jint>(reinterpret_cast<uintptr_t>(moov))); 28} 29 30static SkMovie* J2Movie(JNIEnv* env, jobject movie) { 31 SkASSERT(env); 32 SkASSERT(movie); 33 SkASSERT(env->IsInstanceOf(movie, gMovie_class)); 34 SkMovie* m = (SkMovie*)env->GetIntField(movie, gMovie_nativeInstanceID); 35 SkASSERT(m); 36 return m; 37} 38 39/////////////////////////////////////////////////////////////////////////////// 40 41static int movie_width(JNIEnv* env, jobject movie) { 42 NPE_CHECK_RETURN_ZERO(env, movie); 43 return J2Movie(env, movie)->width(); 44} 45 46static int movie_height(JNIEnv* env, jobject movie) { 47 NPE_CHECK_RETURN_ZERO(env, movie); 48 return J2Movie(env, movie)->height(); 49} 50 51static jboolean movie_isOpaque(JNIEnv* env, jobject movie) { 52 NPE_CHECK_RETURN_ZERO(env, movie); 53 return J2Movie(env, movie)->isOpaque(); 54} 55 56static int movie_duration(JNIEnv* env, jobject movie) { 57 NPE_CHECK_RETURN_ZERO(env, movie); 58 return J2Movie(env, movie)->duration(); 59} 60 61static jboolean movie_setTime(JNIEnv* env, jobject movie, int ms) { 62 NPE_CHECK_RETURN_ZERO(env, movie); 63 return J2Movie(env, movie)->setTime(ms); 64} 65 66static void movie_draw(JNIEnv* env, jobject movie, jobject canvas, 67 jfloat fx, jfloat fy, jobject jpaint) { 68 NPE_CHECK_RETURN_VOID(env, movie); 69 NPE_CHECK_RETURN_VOID(env, canvas); 70 // its OK for paint to be null 71 72 SkMovie* m = J2Movie(env, movie); 73 SkCanvas* c = GraphicsJNI::getNativeCanvas(env, canvas); 74 SkScalar sx = SkFloatToScalar(fx); 75 SkScalar sy = SkFloatToScalar(fy); 76 const SkBitmap& b = m->bitmap(); 77 const SkPaint* p = jpaint ? GraphicsJNI::getNativePaint(env, jpaint) : NULL; 78 79 c->drawBitmap(b, sx, sy, p); 80} 81 82static jobject movie_decodeStream(JNIEnv* env, jobject clazz, jobject istream) { 83 84 NPE_CHECK_RETURN_ZERO(env, istream); 85 86 // what is the lifetime of the array? Can the skstream hold onto it? 87 jbyteArray byteArray = env->NewByteArray(16*1024); 88 SkStream* strm = CreateJavaInputStreamAdaptor(env, istream, byteArray); 89 if (NULL == strm) { 90 return 0; 91 } 92 93 SkMovie* moov = SkMovie::DecodeStream(strm); 94 strm->unref(); 95 return create_jmovie(env, moov); 96} 97 98static jobject movie_decodeByteArray(JNIEnv* env, jobject clazz, 99 jbyteArray byteArray, 100 int offset, int length) { 101 102 NPE_CHECK_RETURN_ZERO(env, byteArray); 103 104 int totalLength = env->GetArrayLength(byteArray); 105 if ((offset | length) < 0 || offset + length > totalLength) { 106 doThrowAIOOBE(env); 107 return 0; 108 } 109 110 AutoJavaByteArray ar(env, byteArray); 111 SkMovie* moov = SkMovie::DecodeMemory(ar.ptr() + offset, length); 112 return create_jmovie(env, moov); 113} 114 115static void movie_destructor(JNIEnv* env, jobject, SkMovie* movie) { 116 delete movie; 117} 118 119////////////////////////////////////////////////////////////////////////////////////////////// 120 121#include <android_runtime/AndroidRuntime.h> 122 123static JNINativeMethod gMethods[] = { 124 { "width", "()I", (void*)movie_width }, 125 { "height", "()I", (void*)movie_height }, 126 { "isOpaque", "()Z", (void*)movie_isOpaque }, 127 { "duration", "()I", (void*)movie_duration }, 128 { "setTime", "(I)Z", (void*)movie_setTime }, 129 { "draw", "(Landroid/graphics/Canvas;FFLandroid/graphics/Paint;)V", 130 (void*)movie_draw }, 131 { "decodeStream", "(Ljava/io/InputStream;)Landroid/graphics/Movie;", 132 (void*)movie_decodeStream }, 133 { "nativeDestructor","(I)V", (void*)movie_destructor }, 134 { "decodeByteArray", "([BII)Landroid/graphics/Movie;", 135 (void*)movie_decodeByteArray }, 136}; 137 138#define kClassPathName "android/graphics/Movie" 139 140#define RETURN_ERR_IF_NULL(value) do { if (!(value)) { assert(0); return -1; } } while (false) 141 142int register_android_graphics_Movie(JNIEnv* env) 143{ 144 gMovie_class = env->FindClass(kClassPathName); 145 RETURN_ERR_IF_NULL(gMovie_class); 146 gMovie_class = (jclass)env->NewGlobalRef(gMovie_class); 147 148 gMovie_constructorMethodID = env->GetMethodID(gMovie_class, "<init>", "(I)V"); 149 RETURN_ERR_IF_NULL(gMovie_constructorMethodID); 150 151 gMovie_nativeInstanceID = env->GetFieldID(gMovie_class, "mNativeMovie", "I"); 152 RETURN_ERR_IF_NULL(gMovie_nativeInstanceID); 153 154 return android::AndroidRuntime::registerNativeMethods(env, kClassPathName, 155 gMethods, SK_ARRAY_COUNT(gMethods)); 156} 157