160126efd7d905ca24822765c6dafac17fef278abBen Wagner#include "CreateJavaOutputStreamAdaptor.h" 260126efd7d905ca24822765c6dafac17fef278abBen Wagner#include "GraphicsJNI.h" 3ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III#include "ScopedLocalRef.h" 47315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III#include "SkFrontBufferedStream.h" 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkMovie.h" 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkStream.h" 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "SkUtils.h" 8ca32021b43f326af7d3f4ae041f8db297f98a518Leon Scroggins III#include "Utils.h" 960126efd7d905ca24822765c6dafac17fef278abBen Wagner#include "core_jni_helpers.h" 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <androidfw/Asset.h> 12b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian#include <androidfw/ResourceTypes.h> 13dccca44ffda4836b56a21da95a046c9708ffd49csergeyv#include <hwui/Canvas.h> 14dccca44ffda4836b56a21da95a046c9708ffd49csergeyv#include <hwui/Paint.h> 1560126efd7d905ca24822765c6dafac17fef278abBen Wagner#include <jni.h> 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <netinet/in.h> 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, 27dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhat static_cast<jlong>(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)); 34dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhat SkMovie* m = (SkMovie*)env->GetLongField(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 41dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhatstatic jint movie_width(JNIEnv* env, jobject movie) { 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NPE_CHECK_RETURN_ZERO(env, movie); 43dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhat return static_cast<jint>(J2Movie(env, movie)->width()); 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 46dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhatstatic jint movie_height(JNIEnv* env, jobject movie) { 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NPE_CHECK_RETURN_ZERO(env, movie); 48dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhat return static_cast<jint>(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); 53dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhat return J2Movie(env, movie)->isOpaque() ? JNI_TRUE : JNI_FALSE; 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 56dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhatstatic jint movie_duration(JNIEnv* env, jobject movie) { 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NPE_CHECK_RETURN_ZERO(env, movie); 58dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhat return static_cast<jint>(J2Movie(env, movie)->duration()); 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 61dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhatstatic jboolean movie_setTime(JNIEnv* env, jobject movie, jint ms) { 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NPE_CHECK_RETURN_ZERO(env, movie); 63dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhat return J2Movie(env, movie)->setTime(ms) ? JNI_TRUE : JNI_FALSE; 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 66304cc5387478618164cd9167f12564f91eb6cc66Derek Sollenbergerstatic void movie_draw(JNIEnv* env, jobject movie, jlong canvasHandle, 67ab22c1c792bc5f422a029a4ab6a23861e44136d8Derek Sollenberger jfloat fx, jfloat fy, jlong paintHandle) { 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NPE_CHECK_RETURN_VOID(env, movie); 69304cc5387478618164cd9167f12564f91eb6cc66Derek Sollenberger 70304cc5387478618164cd9167f12564f91eb6cc66Derek Sollenberger android::Canvas* c = reinterpret_cast<android::Canvas*>(canvasHandle); 71304cc5387478618164cd9167f12564f91eb6cc66Derek Sollenberger const android::Paint* p = reinterpret_cast<android::Paint*>(paintHandle); 72304cc5387478618164cd9167f12564f91eb6cc66Derek Sollenberger 73304cc5387478618164cd9167f12564f91eb6cc66Derek Sollenberger // Canvas should never be NULL. However paint is an optional parameter and 74304cc5387478618164cd9167f12564f91eb6cc66Derek Sollenberger // therefore may be NULL. 75304cc5387478618164cd9167f12564f91eb6cc66Derek Sollenberger SkASSERT(c != NULL); 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SkMovie* m = J2Movie(env, movie); 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const SkBitmap& b = m->bitmap(); 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 802e0103eb340822f9d580c1aa8492bae8394b8243Leon Scroggins III c->drawBitmap(b, fx, fy, p); 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 83dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhatstatic jobject movie_decodeAsset(JNIEnv* env, jobject clazz, jlong native_asset) { 847315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III android::Asset* asset = reinterpret_cast<android::Asset*>(native_asset); 857315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III if (asset == NULL) return NULL; 8660126efd7d905ca24822765c6dafac17fef278abBen Wagner android::AssetStreamAdaptor stream(asset); 8760126efd7d905ca24822765c6dafac17fef278abBen Wagner SkMovie* moov = SkMovie::DecodeStream(&stream); 887315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III return create_jmovie(env, moov); 897315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III} 907315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jobject movie_decodeStream(JNIEnv* env, jobject clazz, jobject istream) { 928451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NPE_CHECK_RETURN_ZERO(env, istream); 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 957315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III jbyteArray byteArray = env->NewByteArray(16*1024); 967315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III ScopedLocalRef<jbyteArray> scoper(env, byteArray); 977315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III SkStream* strm = CreateJavaInputStreamAdaptor(env, istream, byteArray); 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (NULL == strm) { 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1027315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III // Need to buffer enough input to be able to rewind as much as might be read by a decoder 1037315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III // trying to determine the stream's format. The only decoder for movies is GIF, which 1047315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III // will only read 6. 1057315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III // FIXME: Get this number from SkImageDecoder 1063449789b9ca58fee7e5cd02ff89d544f4a6bc9b5Leon Scroggins III // bufferedStream takes ownership of strm 10760126efd7d905ca24822765c6dafac17fef278abBen Wagner std::unique_ptr<SkStreamRewindable> bufferedStream(SkFrontBufferedStream::Create(strm, 6)); 1087315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III SkASSERT(bufferedStream.get() != NULL); 1097315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III 11060126efd7d905ca24822765c6dafac17fef278abBen Wagner SkMovie* moov = SkMovie::DecodeStream(bufferedStream.get()); 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return create_jmovie(env, moov); 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jobject movie_decodeByteArray(JNIEnv* env, jobject clazz, 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jbyteArray byteArray, 116dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhat jint offset, jint length) { 1178451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NPE_CHECK_RETURN_ZERO(env, byteArray); 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int totalLength = env->GetArrayLength(byteArray); 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((offset | length) < 0 || offset + length > totalLength) { 1228451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes doThrowAIOOBE(env); 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AutoJavaByteArray ar(env, byteArray); 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SkMovie* moov = SkMovie::DecodeMemory(ar.ptr() + offset, length); 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return create_jmovie(env, moov); 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 131dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhatstatic void movie_destructor(JNIEnv* env, jobject, jlong movieHandle) { 132dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhat SkMovie* movie = (SkMovie*) movieHandle; 13308d7778f081aae745e6ad9e5350221b21dbf352eKimiyoshi Kusaka delete movie; 13408d7778f081aae745e6ad9e5350221b21dbf352eKimiyoshi Kusaka} 13508d7778f081aae745e6ad9e5350221b21dbf352eKimiyoshi Kusaka 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project////////////////////////////////////////////////////////////////////////////////////////////// 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13876f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod gMethods[] = { 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { "width", "()I", (void*)movie_width }, 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { "height", "()I", (void*)movie_height }, 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { "isOpaque", "()Z", (void*)movie_isOpaque }, 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { "duration", "()I", (void*)movie_duration }, 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { "setTime", "(I)Z", (void*)movie_setTime }, 144304cc5387478618164cd9167f12564f91eb6cc66Derek Sollenberger { "nDraw", "(JFFJ)V", 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (void*)movie_draw }, 146dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhat { "nativeDecodeAsset", "(J)Landroid/graphics/Movie;", 1477315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III (void*)movie_decodeAsset }, 1487315f1baee19476363235127bc1438e2a291fa15Leon Scroggins III { "nativeDecodeStream", "(Ljava/io/InputStream;)Landroid/graphics/Movie;", 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (void*)movie_decodeStream }, 150dcaf5593ddbfe8e1cacaf07813b1e827ba4dba8cAshok Bhat { "nativeDestructor","(J)V", (void*)movie_destructor }, 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { "decodeByteArray", "([BII)Landroid/graphics/Movie;", 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (void*)movie_decodeByteArray }, 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_graphics_Movie(JNIEnv* env) 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 157ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe gMovie_class = android::FindClassOrDie(env, "android/graphics/Movie"); 158ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe gMovie_class = android::MakeGlobalRefOrDie(env, gMovie_class); 1598451b25a4422656bbd6657a5855e69c0f4d53c74Elliott Hughes 160ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe gMovie_constructorMethodID = android::GetMethodIDOrDie(env, gMovie_class, "<init>", "(J)V"); 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 162ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe gMovie_nativeInstanceID = android::GetFieldIDOrDie(env, gMovie_class, "mNativeMovie", "J"); 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 164ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe return android::RegisterMethodsOrDie(env, "android/graphics/Movie", gMethods, NELEM(gMethods)); 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 166