diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2008-10-21 07:00:00 -0700 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2008-10-21 07:00:00 -0700 |
commit | 54b6cfa9a9e5b861a9930af873580d6dc20f773c (patch) | |
tree | 35051494d2af230dce54d6b31c6af8fc24091316 /core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp | |
download | frameworks_base-54b6cfa9a9e5b861a9930af873580d6dc20f773c.zip frameworks_base-54b6cfa9a9e5b861a9930af873580d6dc20f773c.tar.gz frameworks_base-54b6cfa9a9e5b861a9930af873580d6dc20f773c.tar.bz2 |
Initial Contribution
Diffstat (limited to 'core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp')
-rw-r--r-- | core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp new file mode 100644 index 0000000..002fdf9 --- /dev/null +++ b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp @@ -0,0 +1,212 @@ +#include "CreateJavaOutputStreamAdaptor.h" + +#define RETURN_NULL_IF_NULL(value) \ + do { if (!(value)) { SkASSERT(0); return NULL; } } while (false) + +static jclass gInputStream_Clazz; +static jmethodID gInputStream_resetMethodID; +static jmethodID gInputStream_availableMethodID; +static jmethodID gInputStream_readMethodID; +static jmethodID gInputStream_skipMethodID; + +class JavaInputStreamAdaptor : public SkStream { +public: + JavaInputStreamAdaptor(JNIEnv* env, jobject js, jbyteArray ar) + : fEnv(env), fJavaInputStream(js), fJavaByteArray(ar) { + SkASSERT(ar); + fCapacity = env->GetArrayLength(ar); + SkASSERT(fCapacity > 0); + fBytesRead = 0; + } + + virtual bool rewind() { + JNIEnv* env = fEnv; + + fBytesRead = 0; + + env->CallVoidMethod(fJavaInputStream, gInputStream_resetMethodID); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + env->ExceptionClear(); + printf("------- reset threw an exception\n"); + return false; + } + return true; + } + + virtual size_t read(void* buffer, size_t size) { + JNIEnv* env = fEnv; + + if (buffer == NULL && size == 0) { + jint avail = env->CallIntMethod(fJavaInputStream, + gInputStream_availableMethodID); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + env->ExceptionClear(); + printf("------- available threw an exception\n"); + avail = 0; + } + return avail; + } + + size_t bytesRead = 0; + + if (buffer == NULL) { // skip + jlong skipped = env->CallLongMethod(fJavaInputStream, + gInputStream_skipMethodID, (jlong)size); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + env->ExceptionClear(); + printf("------- available threw an exception\n"); + return 0; + } + if (skipped < 0) { + return 0; + } + return (size_t)skipped; + } + + // read the bytes + do { + size_t requested = size; + if (requested > fCapacity) + requested = fCapacity; + + jint n = env->CallIntMethod(fJavaInputStream, + gInputStream_readMethodID, fJavaByteArray, 0, requested); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + env->ExceptionClear(); + printf("---- read threw an exception\n"); + return 0; + } + + if (n <= 0) { + break; // eof + } + + jbyte* array = env->GetByteArrayElements(fJavaByteArray, NULL); + memcpy(buffer, array, n); + env->ReleaseByteArrayElements(fJavaByteArray, array, 0); + + buffer = (void*)((char*)buffer + n); + bytesRead += n; + size -= n; + fBytesRead += n; + } while (size != 0); + + return bytesRead; + } + +private: + JNIEnv* fEnv; + jobject fJavaInputStream; // the caller owns this object + jbyteArray fJavaByteArray; // the caller owns this object + size_t fCapacity; + size_t fBytesRead; +}; + +SkStream* CreateJavaInputStreamAdaptor(JNIEnv* env, jobject stream, + jbyteArray storage) { + static bool gInited; + + if (!gInited) { + gInputStream_Clazz = env->FindClass("java/io/InputStream"); + RETURN_NULL_IF_NULL(gInputStream_Clazz); + gInputStream_Clazz = (jclass)env->NewGlobalRef(gInputStream_Clazz); + + gInputStream_resetMethodID = env->GetMethodID(gInputStream_Clazz, + "reset", "()V"); + gInputStream_availableMethodID = env->GetMethodID(gInputStream_Clazz, + "available", "()I"); + gInputStream_readMethodID = env->GetMethodID(gInputStream_Clazz, + "read", "([BII)I"); + gInputStream_skipMethodID = env->GetMethodID(gInputStream_Clazz, + "skip", "(J)J"); + + RETURN_NULL_IF_NULL(gInputStream_resetMethodID); + RETURN_NULL_IF_NULL(gInputStream_availableMethodID); + RETURN_NULL_IF_NULL(gInputStream_availableMethodID); + RETURN_NULL_IF_NULL(gInputStream_skipMethodID); + + gInited = true; + } + + return new JavaInputStreamAdaptor(env, stream, storage); +} + +/////////////////////////////////////////////////////////////////////////////// + +static jclass gOutputStream_Clazz; +static jmethodID gOutputStream_writeMethodID; +static jmethodID gOutputStream_flushMethodID; + +class SkJavaOutputStream : public SkWStream { +public: + SkJavaOutputStream(JNIEnv* env, jobject stream, jbyteArray storage) + : fEnv(env), fJavaOutputStream(stream), fJavaByteArray(storage) { + fCapacity = env->GetArrayLength(storage); + } + + virtual bool write(const void* buffer, size_t size) { + JNIEnv* env = fEnv; + jbyteArray storage = fJavaByteArray; + + while (size > 0) { + size_t requested = size; + if (requested > fCapacity) { + requested = fCapacity; + } + + jbyte* array = env->GetByteArrayElements(storage, NULL); + memcpy(array, buffer, requested); + env->ReleaseByteArrayElements(storage, array, 0); + + fEnv->CallVoidMethod(fJavaOutputStream, gOutputStream_writeMethodID, + storage, 0, requested); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + env->ExceptionClear(); + printf("------- write threw an exception\n"); + return false; + } + + buffer = (void*)((char*)buffer + requested); + size -= requested; + } + return true; + } + + virtual void flush() { + fEnv->CallVoidMethod(fJavaOutputStream, gOutputStream_flushMethodID); + } + +private: + JNIEnv* fEnv; + jobject fJavaOutputStream; // the caller owns this object + jbyteArray fJavaByteArray; // the caller owns this object + size_t fCapacity; +}; + +SkWStream* CreateJavaOutputStreamAdaptor(JNIEnv* env, jobject stream, + jbyteArray storage) { + static bool gInited; + + if (!gInited) { + gOutputStream_Clazz = env->FindClass("java/io/OutputStream"); + RETURN_NULL_IF_NULL(gOutputStream_Clazz); + gOutputStream_Clazz = (jclass)env->NewGlobalRef(gOutputStream_Clazz); + + gOutputStream_writeMethodID = env->GetMethodID(gOutputStream_Clazz, + "write", "([BII)V"); + RETURN_NULL_IF_NULL(gOutputStream_writeMethodID); + gOutputStream_flushMethodID = env->GetMethodID(gOutputStream_Clazz, + "flush", "()V"); + RETURN_NULL_IF_NULL(gOutputStream_flushMethodID); + + gInited = true; + } + + return new SkJavaOutputStream(env, stream, storage); +} + |