19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkMovie.h"
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkStream.h"
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "GraphicsJNI.h"
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkTemplates.h"
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkUtils.h"
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "CreateJavaOutputStreamAdaptor.h"
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <androidfw/Asset.h>
9b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <androidfw/ResourceTypes.h>
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <netinet/in.h>
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if 0
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    #define TRACE_BITMAP(code)  code
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    #define TRACE_BITMAP(code)
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jclass       gMovie_class;
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jmethodID    gMovie_constructorMethodID;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID     gMovie_nativeInstanceID;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectjobject create_jmovie(JNIEnv* env, SkMovie* moov) {
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (NULL == moov) {
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return NULL;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
26cf6f7a0f006c0fcf59bb634cbe79f2a8500fd92aElliott Hughes    return env->NewObject(gMovie_class, gMovie_constructorMethodID,
27cf6f7a0f006c0fcf59bb634cbe79f2a8500fd92aElliott Hughes            static_cast<jint>(reinterpret_cast<uintptr_t>(moov)));
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic SkMovie* J2Movie(JNIEnv* env, jobject movie) {
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkASSERT(env);
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkASSERT(movie);
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkASSERT(env->IsInstanceOf(movie, gMovie_class));
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkMovie* m = (SkMovie*)env->GetIntField(movie, gMovie_nativeInstanceID);
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkASSERT(m);
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return m;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int movie_width(JNIEnv* env, jobject movie) {
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NPE_CHECK_RETURN_ZERO(env, movie);
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return J2Movie(env, movie)->width();
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int movie_height(JNIEnv* env, jobject movie) {
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NPE_CHECK_RETURN_ZERO(env, movie);
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return J2Movie(env, movie)->height();
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jboolean movie_isOpaque(JNIEnv* env, jobject movie) {
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NPE_CHECK_RETURN_ZERO(env, movie);
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return J2Movie(env, movie)->isOpaque();
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int movie_duration(JNIEnv* env, jobject movie) {
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NPE_CHECK_RETURN_ZERO(env, movie);
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return J2Movie(env, movie)->duration();
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jboolean movie_setTime(JNIEnv* env, jobject movie, int ms) {
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NPE_CHECK_RETURN_ZERO(env, movie);
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return J2Movie(env, movie)->setTime(ms);
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void movie_draw(JNIEnv* env, jobject movie, jobject canvas,
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                       jfloat fx, jfloat fy, jobject jpaint) {
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NPE_CHECK_RETURN_VOID(env, movie);
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NPE_CHECK_RETURN_VOID(env, canvas);
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // its OK for paint to be null
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkMovie* m = J2Movie(env, movie);
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkCanvas* c = GraphicsJNI::getNativeCanvas(env, canvas);
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkScalar sx = SkFloatToScalar(fx);
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkScalar sy = SkFloatToScalar(fy);
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const SkBitmap& b = m->bitmap();
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    const SkPaint* p = jpaint ? GraphicsJNI::getNativePaint(env, jpaint) : NULL;
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    c->drawBitmap(b, sx, sy, p);
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jobject movie_decodeStream(JNIEnv* env, jobject clazz, jobject istream) {
838451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NPE_CHECK_RETURN_ZERO(env, istream);
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // what is the lifetime of the array? Can the skstream hold onto it?
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jbyteArray byteArray = env->NewByteArray(16*1024);
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkStream* strm = CreateJavaInputStreamAdaptor(env, istream, byteArray);
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (NULL == strm) {
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0;
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkMovie* moov = SkMovie::DecodeStream(strm);
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    strm->unref();
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return create_jmovie(env, moov);
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jobject movie_decodeByteArray(JNIEnv* env, jobject clazz,
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                     jbyteArray byteArray,
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                     int offset, int length) {
1018451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    NPE_CHECK_RETURN_ZERO(env, byteArray);
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int totalLength = env->GetArrayLength(byteArray);
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if ((offset | length) < 0 || offset + length > totalLength) {
1068451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes        doThrowAIOOBE(env);
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0;
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    AutoJavaByteArray   ar(env, byteArray);
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SkMovie* moov = SkMovie::DecodeMemory(ar.ptr() + offset, length);
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return create_jmovie(env, moov);
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11508d7778f081aae745e6ad9e5350221b21dbf352eKimiyoshi Kusakastatic void movie_destructor(JNIEnv* env, jobject, SkMovie* movie) {
11608d7778f081aae745e6ad9e5350221b21dbf352eKimiyoshi Kusaka    delete movie;
11708d7778f081aae745e6ad9e5350221b21dbf352eKimiyoshi Kusaka}
11808d7778f081aae745e6ad9e5350221b21dbf352eKimiyoshi Kusaka
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//////////////////////////////////////////////////////////////////////////////////////////////
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <android_runtime/AndroidRuntime.h>
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod gMethods[] = {
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {   "width",    "()I",  (void*)movie_width  },
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {   "height",   "()I",  (void*)movie_height  },
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {   "isOpaque", "()Z",  (void*)movie_isOpaque  },
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {   "duration", "()I",  (void*)movie_duration  },
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {   "setTime",  "(I)Z", (void*)movie_setTime  },
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {   "draw",     "(Landroid/graphics/Canvas;FFLandroid/graphics/Paint;)V",
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            (void*)movie_draw  },
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "decodeStream", "(Ljava/io/InputStream;)Landroid/graphics/Movie;",
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            (void*)movie_decodeStream },
13308d7778f081aae745e6ad9e5350221b21dbf352eKimiyoshi Kusaka    { "nativeDestructor","(I)V", (void*)movie_destructor },
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    { "decodeByteArray", "([BII)Landroid/graphics/Movie;",
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            (void*)movie_decodeByteArray },
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define kClassPathName  "android/graphics/Movie"
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define RETURN_ERR_IF_NULL(value)   do { if (!(value)) { assert(0); return -1; } } while (false)
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_graphics_Movie(JNIEnv* env)
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    gMovie_class = env->FindClass(kClassPathName);
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    RETURN_ERR_IF_NULL(gMovie_class);
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    gMovie_class = (jclass)env->NewGlobalRef(gMovie_class);
1478451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    gMovie_constructorMethodID = env->GetMethodID(gMovie_class, "<init>", "(I)V");
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    RETURN_ERR_IF_NULL(gMovie_constructorMethodID);
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    gMovie_nativeInstanceID = env->GetFieldID(gMovie_class, "mNativeMovie", "I");
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    RETURN_ERR_IF_NULL(gMovie_nativeInstanceID);
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return android::AndroidRuntime::registerNativeMethods(env, kClassPathName,
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                       gMethods, SK_ARRAY_COUNT(gMethods));
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
157