Loading core/jni/android/graphics/BitmapFactory.cpp +10 −5 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ #include "BitmapFactory.h" #include "NinePatchPeeker.h" #include "SkData.h" #include "SkFrontBufferedStream.h" #include "SkImageDecoder.h" #include "SkImageRef_ashmem.h" #include "SkImageRef_GlobalPool.h" Loading Loading @@ -120,7 +121,7 @@ static void scaleNinePatchChunk(android::Res_png_9patch* chunk, float scale) { } } static SkPixelRef* installPixelRef(SkBitmap* bitmap, SkStream* stream, static SkPixelRef* installPixelRef(SkBitmap* bitmap, SkStreamRewindable* stream, int sampleSize, bool ditherImage) { SkImageRef* pr; Loading Loading @@ -465,13 +466,17 @@ static jobject nativeDecodeStream(JNIEnv* env, jobject clazz, jobject is, jbyteA jobject padding, jobject options) { jobject bitmap = NULL; SkAutoTUnref<SkStreamRewindable> stream(GetRewindableStream(env, is, storage)); SkAutoTUnref<SkStream> stream(CreateJavaInputStreamAdaptor(env, is, storage)); if (stream.get()) { // Need to buffer enough input to be able to rewind as much as might be read by a decoder // trying to determine the stream's format. Currently the most is 64, read by // SkImageDecoder_libwebp. // FIXME: Get this number from SkImageDecoder SkAutoTUnref<SkStreamRewindable> bufferedStream(SkFrontBufferedStream::Create(stream, 64)); SkASSERT(bufferedStream.get() != NULL); // for now we don't allow purgeable with java inputstreams // FIXME: GetRewindableStream may have made a copy, in which case // purgeable should be allowed. bitmap = doDecode(env, stream, padding, options, false, false); bitmap = doDecode(env, bufferedStream, padding, options, false, false); } return bitmap; } Loading core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp +1 −169 Original line number Diff line number Diff line Loading @@ -5,18 +5,12 @@ #include "SkStream.h" #include "SkTypes.h" #include "Utils.h" #include <androidfw/Asset.h> static jmethodID gInputStream_resetMethodID; static jmethodID gInputStream_markMethodID; static jmethodID gInputStream_markSupportedMethodID; static jmethodID gInputStream_readMethodID; static jmethodID gInputStream_skipMethodID; class RewindableJavaStream; /** * Non-rewindable wrapper for a Java InputStream. * Wrapper for a Java InputStream. */ class JavaInputStreamAdaptor : public SkStream { public: Loading Loading @@ -64,25 +58,6 @@ public: } private: // Does not override rewind, since a JavaInputStreamAdaptor's interface // does not support rewinding. RewindableJavaStream, which is a friend, // will be able to call this method to rewind. bool doRewind() { JNIEnv* env = fEnv; fBytesRead = 0; fIsAtEnd = false; env->CallVoidMethod(fJavaInputStream, gInputStream_resetMethodID); if (env->ExceptionCheck()) { env->ExceptionDescribe(); env->ExceptionClear(); SkDebugf("------- reset threw an exception\n"); return false; } return true; } size_t doRead(void* buffer, size_t size) { JNIEnv* env = fEnv; size_t bytesRead = 0; Loading Loading @@ -148,9 +123,6 @@ private: size_t fCapacity; size_t fBytesRead; bool fIsAtEnd; // Allows access to doRewind and fBytesRead. friend class RewindableJavaStream; }; SkStream* CreateJavaInputStreamAdaptor(JNIEnv* env, jobject stream, Loading Loading @@ -190,123 +162,6 @@ SkStreamRewindable* CopyJavaInputStream(JNIEnv* env, jobject stream, return adaptor_to_mem_stream(adaptor.get()); } /** * Wrapper for a Java InputStream which is rewindable and * has a length. */ class RewindableJavaStream : public SkStreamRewindable { public: // RewindableJavaStream takes ownership of adaptor. RewindableJavaStream(JavaInputStreamAdaptor* adaptor, size_t length) : fAdaptor(adaptor) , fLength(length) { SkASSERT(fAdaptor != NULL); } virtual ~RewindableJavaStream() { fAdaptor->unref(); } virtual bool rewind() { return fAdaptor->doRewind(); } virtual size_t read(void* buffer, size_t size) { return fAdaptor->read(buffer, size); } virtual bool isAtEnd() const { return fAdaptor->isAtEnd(); } virtual size_t getLength() const { return fLength; } virtual bool hasLength() const { return true; } virtual SkStreamRewindable* duplicate() const { // Duplicating this stream requires rewinding and // reading, which modify this Stream (and could // fail, leaving this one invalid). SkASSERT(false); return NULL; } private: JavaInputStreamAdaptor* fAdaptor; const size_t fLength; }; static jclass gByteArrayInputStream_Clazz; static jfieldID gCountField; static jfieldID gPosField; /** * If jstream is a ByteArrayInputStream, return its remaining length. Otherwise * return 0. */ static size_t get_length_from_byte_array_stream(JNIEnv* env, jobject jstream) { if (env->IsInstanceOf(jstream, gByteArrayInputStream_Clazz)) { // Return the remaining length, to keep the same behavior of using the rest of the // stream. return env->GetIntField(jstream, gCountField) - env->GetIntField(jstream, gPosField); } return 0; } /** * If jstream is a class that has a length, return it. Otherwise * return 0. * Only checks for a set of subclasses. */ static size_t get_length_if_supported(JNIEnv* env, jobject jstream) { size_t len = get_length_from_byte_array_stream(env, jstream); if (len > 0) { return len; } return 0; } SkStreamRewindable* GetRewindableStream(JNIEnv* env, jobject stream, jbyteArray storage) { SkAutoTUnref<SkStream> adaptor(CreateJavaInputStreamAdaptor(env, stream, storage)); if (NULL == adaptor.get()) { return NULL; } const size_t length = get_length_if_supported(env, stream); if (length > 0 && env->CallBooleanMethod(stream, gInputStream_markSupportedMethodID)) { // Set the readLimit for mark to the end of the stream, so it can // be rewound regardless of how much has been read. env->CallVoidMethod(stream, gInputStream_markMethodID, length); // RewindableJavaStream will unref adaptor when it is destroyed. return new RewindableJavaStream(static_cast<JavaInputStreamAdaptor*>(adaptor.detach()), length); } return adaptor_to_mem_stream(adaptor.get()); } static jclass gAssetInputStream_Clazz; static jmethodID gGetAssetIntMethodID; android::AssetStreamAdaptor* CheckForAssetStream(JNIEnv* env, jobject jstream) { if (!env->IsInstanceOf(jstream, gAssetInputStream_Clazz)) { return NULL; } jint jasset = env->CallIntMethod(jstream, gGetAssetIntMethodID); android::Asset* a = reinterpret_cast<android::Asset*>(jasset); if (NULL == a) { jniThrowNullPointerException(env, "NULL native asset"); return NULL; } return new android::AssetStreamAdaptor(a); } /////////////////////////////////////////////////////////////////////////////// static jmethodID gOutputStream_writeMethodID; Loading Loading @@ -382,13 +237,6 @@ static jclass findClassCheck(JNIEnv* env, const char classname[]) { return clazz; } static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz, const char fieldname[], const char type[]) { jfieldID id = env->GetFieldID(clazz, fieldname, type); SkASSERT(!env->ExceptionCheck()); return id; } static jmethodID getMethodIDCheck(JNIEnv* env, jclass clazz, const char methodname[], const char type[]) { jmethodID id = env->GetMethodID(clazz, methodname, type); Loading @@ -398,25 +246,9 @@ static jmethodID getMethodIDCheck(JNIEnv* env, jclass clazz, int register_android_graphics_CreateJavaOutputStreamAdaptor(JNIEnv* env) { jclass inputStream_Clazz = findClassCheck(env, "java/io/InputStream"); gInputStream_resetMethodID = getMethodIDCheck(env, inputStream_Clazz, "reset", "()V"); gInputStream_markMethodID = getMethodIDCheck(env, inputStream_Clazz, "mark", "(I)V"); gInputStream_markSupportedMethodID = getMethodIDCheck(env, inputStream_Clazz, "markSupported", "()Z"); gInputStream_readMethodID = getMethodIDCheck(env, inputStream_Clazz, "read", "([BII)I"); gInputStream_skipMethodID = getMethodIDCheck(env, inputStream_Clazz, "skip", "(J)J"); gByteArrayInputStream_Clazz = findClassCheck(env, "java/io/ByteArrayInputStream"); // Ref gByteArrayInputStream_Clazz so we can continue to refer to it when // calling IsInstance. gByteArrayInputStream_Clazz = (jclass) env->NewGlobalRef(gByteArrayInputStream_Clazz); gCountField = getFieldIDCheck(env, gByteArrayInputStream_Clazz, "count", "I"); gPosField = getFieldIDCheck(env, gByteArrayInputStream_Clazz, "pos", "I"); gAssetInputStream_Clazz = findClassCheck(env, "android/content/res/AssetManager$AssetInputStream"); // Ref gAssetInputStream_Clazz so we can continue to refer to it when // calling IsInstance. gAssetInputStream_Clazz = (jclass) env->NewGlobalRef(gAssetInputStream_Clazz); gGetAssetIntMethodID = getMethodIDCheck(env, gAssetInputStream_Clazz, "getAssetInt", "()I"); jclass outputStream_Clazz = findClassCheck(env, "java/io/OutputStream"); gOutputStream_writeMethodID = getMethodIDCheck(env, outputStream_Clazz, "write", "([BII)V"); gOutputStream_flushMethodID = getMethodIDCheck(env, outputStream_Clazz, "flush", "()V"); Loading core/jni/android/graphics/CreateJavaOutputStreamAdaptor.h +2 −31 Original line number Diff line number Diff line Loading @@ -4,10 +4,6 @@ //#include <android_runtime/AndroidRuntime.h> #include "jni.h" namespace android { class AssetStreamAdaptor; } class SkMemoryStream; class SkStream; class SkStreamRewindable; Loading @@ -15,6 +11,7 @@ class SkWStream; /** * Return an adaptor from a Java InputStream to an SkStream. * Does not support rewind. * @param env JNIEnv object. * @param stream Pointer to Java InputStream. * @param storage Java byte array for retrieving data from the Loading @@ -28,7 +25,7 @@ SkStream* CreateJavaInputStreamAdaptor(JNIEnv* env, jobject stream, jbyteArray storage); /** * Copy a Java InputStream. * Copy a Java InputStream. The result will be rewindable. * @param env JNIEnv object. * @param stream Pointer to Java InputStream. * @param storage Java byte array for retrieving data from the Loading @@ -39,32 +36,6 @@ SkStream* CreateJavaInputStreamAdaptor(JNIEnv* env, jobject stream, SkStreamRewindable* CopyJavaInputStream(JNIEnv* env, jobject stream, jbyteArray storage); /** * Get a rewindable stream from a Java InputStream. * @param env JNIEnv object. * @param stream Pointer to Java InputStream. * @param storage Java byte array for retrieving data from the * Java InputStream. * @return SkStreamRewindable Either a wrapper around the Java * InputStream, if possible, or a copy which is rewindable. * Since it may be a wrapper, must not be used after the * caller returns, like the result of CreateJavaInputStreamAdaptor. */ SkStreamRewindable* GetRewindableStream(JNIEnv* env, jobject stream, jbyteArray storage); /** * If the Java InputStream is an AssetInputStream, return an adaptor. * This should not be used after the calling function returns, since * the caller may close the asset. Returns NULL if the stream is * not an AssetInputStream. * @param env JNIEnv object. * @param stream Pointer to Java InputStream. * @return AssetStreamAdaptor representing the InputStream, or NULL. * Must not be held onto. */ android::AssetStreamAdaptor* CheckForAssetStream(JNIEnv* env, jobject stream); SkWStream* CreateJavaOutputStreamAdaptor(JNIEnv* env, jobject stream, jbyteArray storage); #endif core/jni/android/graphics/Movie.cpp +23 −10 Original line number Diff line number Diff line #include "ScopedLocalRef.h" #include "SkFrontBufferedStream.h" #include "SkMovie.h" #include "SkStream.h" #include "GraphicsJNI.h" Loading Loading @@ -81,23 +82,33 @@ static void movie_draw(JNIEnv* env, jobject movie, jobject canvas, c->drawBitmap(b, sx, sy, p); } static jobject movie_decodeAsset(JNIEnv* env, jobject clazz, jint native_asset) { android::Asset* asset = reinterpret_cast<android::Asset*>(native_asset); if (asset == NULL) return NULL; SkAutoTUnref<SkStreamRewindable> stream (new android::AssetStreamAdaptor(asset)); SkMovie* moov = SkMovie::DecodeStream(stream.get()); return create_jmovie(env, moov); } static jobject movie_decodeStream(JNIEnv* env, jobject clazz, jobject istream) { NPE_CHECK_RETURN_ZERO(env, istream); SkStreamRewindable* strm = CheckForAssetStream(env, istream); jbyteArray byteArray = NULL; ScopedLocalRef<jbyteArray> scoper(env, NULL); if (NULL == strm) { byteArray = env->NewByteArray(16*1024); scoper.reset(byteArray); strm = GetRewindableStream(env, istream, byteArray); } jbyteArray byteArray = env->NewByteArray(16*1024); ScopedLocalRef<jbyteArray> scoper(env, byteArray); SkStream* strm = CreateJavaInputStreamAdaptor(env, istream, byteArray); if (NULL == strm) { return 0; } SkMovie* moov = SkMovie::DecodeStream(strm); // Need to buffer enough input to be able to rewind as much as might be read by a decoder // trying to determine the stream's format. The only decoder for movies is GIF, which // will only read 6. // FIXME: Get this number from SkImageDecoder SkAutoTUnref<SkStreamRewindable> bufferedStream(SkFrontBufferedStream::Create(strm, 6)); SkASSERT(bufferedStream.get() != NULL); SkMovie* moov = SkMovie::DecodeStream(bufferedStream); strm->unref(); return create_jmovie(env, moov); } Loading Loading @@ -135,7 +146,9 @@ static JNINativeMethod gMethods[] = { { "setTime", "(I)Z", (void*)movie_setTime }, { "draw", "(Landroid/graphics/Canvas;FFLandroid/graphics/Paint;)V", (void*)movie_draw }, { "decodeStream", "(Ljava/io/InputStream;)Landroid/graphics/Movie;", { "nativeDecodeAsset", "(I)Landroid/graphics/Movie;", (void*)movie_decodeAsset }, { "nativeDecodeStream", "(Ljava/io/InputStream;)Landroid/graphics/Movie;", (void*)movie_decodeStream }, { "nativeDestructor","(I)V", (void*)movie_destructor }, { "decodeByteArray", "([BII)Landroid/graphics/Movie;", Loading graphics/java/android/graphics/BitmapFactory.java +14 −10 Original line number Diff line number Diff line Loading @@ -569,10 +569,7 @@ public class BitmapFactory { final int asset = ((AssetManager.AssetInputStream) is).getAssetInt(); bm = nativeDecodeAsset(asset, outPadding, opts); } else { byte [] tempStorage = null; if (opts != null) tempStorage = opts.inTempStorage; if (tempStorage == null) tempStorage = new byte[DECODE_BUFFER_SIZE]; bm = nativeDecodeStream(is, tempStorage, outPadding, opts); bm = decodeStreamInternal(is, outPadding, opts); } if (bm == null && opts != null && opts.inBitmap != null) { Loading @@ -587,6 +584,18 @@ public class BitmapFactory { return bm; } /** * Private helper function for decoding an InputStream natively. Buffers the input enough to * do a rewind as needed, and supplies temporary storage if necessary. is MUST NOT be null. */ private static Bitmap decodeStreamInternal(InputStream is, Rect outPadding, Options opts) { // ASSERT(is != null); byte [] tempStorage = null; if (opts != null) tempStorage = opts.inTempStorage; if (tempStorage == null) tempStorage = new byte[DECODE_BUFFER_SIZE]; return nativeDecodeStream(is, tempStorage, outPadding, opts); } /** * Decode an input stream into a bitmap. If the input stream is null, or * cannot be used to decode a bitmap, the function returns null. Loading Loading @@ -624,13 +633,8 @@ public class BitmapFactory { bm = nativeDecodeFileDescriptor(fd, outPadding, opts); } else { FileInputStream fis = new FileInputStream(fd); // FIXME: If nativeDecodeStream grabbed the pointer to tempStorage // from Options, this code would not need to be duplicated. byte [] tempStorage = null; if (opts != null) tempStorage = opts.inTempStorage; if (tempStorage == null) tempStorage = new byte[DECODE_BUFFER_SIZE]; try { bm = nativeDecodeStream(fis, tempStorage, outPadding, opts); bm = decodeStreamInternal(fis, outPadding, opts); } finally { try { fis.close(); Loading Loading
core/jni/android/graphics/BitmapFactory.cpp +10 −5 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ #include "BitmapFactory.h" #include "NinePatchPeeker.h" #include "SkData.h" #include "SkFrontBufferedStream.h" #include "SkImageDecoder.h" #include "SkImageRef_ashmem.h" #include "SkImageRef_GlobalPool.h" Loading Loading @@ -120,7 +121,7 @@ static void scaleNinePatchChunk(android::Res_png_9patch* chunk, float scale) { } } static SkPixelRef* installPixelRef(SkBitmap* bitmap, SkStream* stream, static SkPixelRef* installPixelRef(SkBitmap* bitmap, SkStreamRewindable* stream, int sampleSize, bool ditherImage) { SkImageRef* pr; Loading Loading @@ -465,13 +466,17 @@ static jobject nativeDecodeStream(JNIEnv* env, jobject clazz, jobject is, jbyteA jobject padding, jobject options) { jobject bitmap = NULL; SkAutoTUnref<SkStreamRewindable> stream(GetRewindableStream(env, is, storage)); SkAutoTUnref<SkStream> stream(CreateJavaInputStreamAdaptor(env, is, storage)); if (stream.get()) { // Need to buffer enough input to be able to rewind as much as might be read by a decoder // trying to determine the stream's format. Currently the most is 64, read by // SkImageDecoder_libwebp. // FIXME: Get this number from SkImageDecoder SkAutoTUnref<SkStreamRewindable> bufferedStream(SkFrontBufferedStream::Create(stream, 64)); SkASSERT(bufferedStream.get() != NULL); // for now we don't allow purgeable with java inputstreams // FIXME: GetRewindableStream may have made a copy, in which case // purgeable should be allowed. bitmap = doDecode(env, stream, padding, options, false, false); bitmap = doDecode(env, bufferedStream, padding, options, false, false); } return bitmap; } Loading
core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp +1 −169 Original line number Diff line number Diff line Loading @@ -5,18 +5,12 @@ #include "SkStream.h" #include "SkTypes.h" #include "Utils.h" #include <androidfw/Asset.h> static jmethodID gInputStream_resetMethodID; static jmethodID gInputStream_markMethodID; static jmethodID gInputStream_markSupportedMethodID; static jmethodID gInputStream_readMethodID; static jmethodID gInputStream_skipMethodID; class RewindableJavaStream; /** * Non-rewindable wrapper for a Java InputStream. * Wrapper for a Java InputStream. */ class JavaInputStreamAdaptor : public SkStream { public: Loading Loading @@ -64,25 +58,6 @@ public: } private: // Does not override rewind, since a JavaInputStreamAdaptor's interface // does not support rewinding. RewindableJavaStream, which is a friend, // will be able to call this method to rewind. bool doRewind() { JNIEnv* env = fEnv; fBytesRead = 0; fIsAtEnd = false; env->CallVoidMethod(fJavaInputStream, gInputStream_resetMethodID); if (env->ExceptionCheck()) { env->ExceptionDescribe(); env->ExceptionClear(); SkDebugf("------- reset threw an exception\n"); return false; } return true; } size_t doRead(void* buffer, size_t size) { JNIEnv* env = fEnv; size_t bytesRead = 0; Loading Loading @@ -148,9 +123,6 @@ private: size_t fCapacity; size_t fBytesRead; bool fIsAtEnd; // Allows access to doRewind and fBytesRead. friend class RewindableJavaStream; }; SkStream* CreateJavaInputStreamAdaptor(JNIEnv* env, jobject stream, Loading Loading @@ -190,123 +162,6 @@ SkStreamRewindable* CopyJavaInputStream(JNIEnv* env, jobject stream, return adaptor_to_mem_stream(adaptor.get()); } /** * Wrapper for a Java InputStream which is rewindable and * has a length. */ class RewindableJavaStream : public SkStreamRewindable { public: // RewindableJavaStream takes ownership of adaptor. RewindableJavaStream(JavaInputStreamAdaptor* adaptor, size_t length) : fAdaptor(adaptor) , fLength(length) { SkASSERT(fAdaptor != NULL); } virtual ~RewindableJavaStream() { fAdaptor->unref(); } virtual bool rewind() { return fAdaptor->doRewind(); } virtual size_t read(void* buffer, size_t size) { return fAdaptor->read(buffer, size); } virtual bool isAtEnd() const { return fAdaptor->isAtEnd(); } virtual size_t getLength() const { return fLength; } virtual bool hasLength() const { return true; } virtual SkStreamRewindable* duplicate() const { // Duplicating this stream requires rewinding and // reading, which modify this Stream (and could // fail, leaving this one invalid). SkASSERT(false); return NULL; } private: JavaInputStreamAdaptor* fAdaptor; const size_t fLength; }; static jclass gByteArrayInputStream_Clazz; static jfieldID gCountField; static jfieldID gPosField; /** * If jstream is a ByteArrayInputStream, return its remaining length. Otherwise * return 0. */ static size_t get_length_from_byte_array_stream(JNIEnv* env, jobject jstream) { if (env->IsInstanceOf(jstream, gByteArrayInputStream_Clazz)) { // Return the remaining length, to keep the same behavior of using the rest of the // stream. return env->GetIntField(jstream, gCountField) - env->GetIntField(jstream, gPosField); } return 0; } /** * If jstream is a class that has a length, return it. Otherwise * return 0. * Only checks for a set of subclasses. */ static size_t get_length_if_supported(JNIEnv* env, jobject jstream) { size_t len = get_length_from_byte_array_stream(env, jstream); if (len > 0) { return len; } return 0; } SkStreamRewindable* GetRewindableStream(JNIEnv* env, jobject stream, jbyteArray storage) { SkAutoTUnref<SkStream> adaptor(CreateJavaInputStreamAdaptor(env, stream, storage)); if (NULL == adaptor.get()) { return NULL; } const size_t length = get_length_if_supported(env, stream); if (length > 0 && env->CallBooleanMethod(stream, gInputStream_markSupportedMethodID)) { // Set the readLimit for mark to the end of the stream, so it can // be rewound regardless of how much has been read. env->CallVoidMethod(stream, gInputStream_markMethodID, length); // RewindableJavaStream will unref adaptor when it is destroyed. return new RewindableJavaStream(static_cast<JavaInputStreamAdaptor*>(adaptor.detach()), length); } return adaptor_to_mem_stream(adaptor.get()); } static jclass gAssetInputStream_Clazz; static jmethodID gGetAssetIntMethodID; android::AssetStreamAdaptor* CheckForAssetStream(JNIEnv* env, jobject jstream) { if (!env->IsInstanceOf(jstream, gAssetInputStream_Clazz)) { return NULL; } jint jasset = env->CallIntMethod(jstream, gGetAssetIntMethodID); android::Asset* a = reinterpret_cast<android::Asset*>(jasset); if (NULL == a) { jniThrowNullPointerException(env, "NULL native asset"); return NULL; } return new android::AssetStreamAdaptor(a); } /////////////////////////////////////////////////////////////////////////////// static jmethodID gOutputStream_writeMethodID; Loading Loading @@ -382,13 +237,6 @@ static jclass findClassCheck(JNIEnv* env, const char classname[]) { return clazz; } static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz, const char fieldname[], const char type[]) { jfieldID id = env->GetFieldID(clazz, fieldname, type); SkASSERT(!env->ExceptionCheck()); return id; } static jmethodID getMethodIDCheck(JNIEnv* env, jclass clazz, const char methodname[], const char type[]) { jmethodID id = env->GetMethodID(clazz, methodname, type); Loading @@ -398,25 +246,9 @@ static jmethodID getMethodIDCheck(JNIEnv* env, jclass clazz, int register_android_graphics_CreateJavaOutputStreamAdaptor(JNIEnv* env) { jclass inputStream_Clazz = findClassCheck(env, "java/io/InputStream"); gInputStream_resetMethodID = getMethodIDCheck(env, inputStream_Clazz, "reset", "()V"); gInputStream_markMethodID = getMethodIDCheck(env, inputStream_Clazz, "mark", "(I)V"); gInputStream_markSupportedMethodID = getMethodIDCheck(env, inputStream_Clazz, "markSupported", "()Z"); gInputStream_readMethodID = getMethodIDCheck(env, inputStream_Clazz, "read", "([BII)I"); gInputStream_skipMethodID = getMethodIDCheck(env, inputStream_Clazz, "skip", "(J)J"); gByteArrayInputStream_Clazz = findClassCheck(env, "java/io/ByteArrayInputStream"); // Ref gByteArrayInputStream_Clazz so we can continue to refer to it when // calling IsInstance. gByteArrayInputStream_Clazz = (jclass) env->NewGlobalRef(gByteArrayInputStream_Clazz); gCountField = getFieldIDCheck(env, gByteArrayInputStream_Clazz, "count", "I"); gPosField = getFieldIDCheck(env, gByteArrayInputStream_Clazz, "pos", "I"); gAssetInputStream_Clazz = findClassCheck(env, "android/content/res/AssetManager$AssetInputStream"); // Ref gAssetInputStream_Clazz so we can continue to refer to it when // calling IsInstance. gAssetInputStream_Clazz = (jclass) env->NewGlobalRef(gAssetInputStream_Clazz); gGetAssetIntMethodID = getMethodIDCheck(env, gAssetInputStream_Clazz, "getAssetInt", "()I"); jclass outputStream_Clazz = findClassCheck(env, "java/io/OutputStream"); gOutputStream_writeMethodID = getMethodIDCheck(env, outputStream_Clazz, "write", "([BII)V"); gOutputStream_flushMethodID = getMethodIDCheck(env, outputStream_Clazz, "flush", "()V"); Loading
core/jni/android/graphics/CreateJavaOutputStreamAdaptor.h +2 −31 Original line number Diff line number Diff line Loading @@ -4,10 +4,6 @@ //#include <android_runtime/AndroidRuntime.h> #include "jni.h" namespace android { class AssetStreamAdaptor; } class SkMemoryStream; class SkStream; class SkStreamRewindable; Loading @@ -15,6 +11,7 @@ class SkWStream; /** * Return an adaptor from a Java InputStream to an SkStream. * Does not support rewind. * @param env JNIEnv object. * @param stream Pointer to Java InputStream. * @param storage Java byte array for retrieving data from the Loading @@ -28,7 +25,7 @@ SkStream* CreateJavaInputStreamAdaptor(JNIEnv* env, jobject stream, jbyteArray storage); /** * Copy a Java InputStream. * Copy a Java InputStream. The result will be rewindable. * @param env JNIEnv object. * @param stream Pointer to Java InputStream. * @param storage Java byte array for retrieving data from the Loading @@ -39,32 +36,6 @@ SkStream* CreateJavaInputStreamAdaptor(JNIEnv* env, jobject stream, SkStreamRewindable* CopyJavaInputStream(JNIEnv* env, jobject stream, jbyteArray storage); /** * Get a rewindable stream from a Java InputStream. * @param env JNIEnv object. * @param stream Pointer to Java InputStream. * @param storage Java byte array for retrieving data from the * Java InputStream. * @return SkStreamRewindable Either a wrapper around the Java * InputStream, if possible, or a copy which is rewindable. * Since it may be a wrapper, must not be used after the * caller returns, like the result of CreateJavaInputStreamAdaptor. */ SkStreamRewindable* GetRewindableStream(JNIEnv* env, jobject stream, jbyteArray storage); /** * If the Java InputStream is an AssetInputStream, return an adaptor. * This should not be used after the calling function returns, since * the caller may close the asset. Returns NULL if the stream is * not an AssetInputStream. * @param env JNIEnv object. * @param stream Pointer to Java InputStream. * @return AssetStreamAdaptor representing the InputStream, or NULL. * Must not be held onto. */ android::AssetStreamAdaptor* CheckForAssetStream(JNIEnv* env, jobject stream); SkWStream* CreateJavaOutputStreamAdaptor(JNIEnv* env, jobject stream, jbyteArray storage); #endif
core/jni/android/graphics/Movie.cpp +23 −10 Original line number Diff line number Diff line #include "ScopedLocalRef.h" #include "SkFrontBufferedStream.h" #include "SkMovie.h" #include "SkStream.h" #include "GraphicsJNI.h" Loading Loading @@ -81,23 +82,33 @@ static void movie_draw(JNIEnv* env, jobject movie, jobject canvas, c->drawBitmap(b, sx, sy, p); } static jobject movie_decodeAsset(JNIEnv* env, jobject clazz, jint native_asset) { android::Asset* asset = reinterpret_cast<android::Asset*>(native_asset); if (asset == NULL) return NULL; SkAutoTUnref<SkStreamRewindable> stream (new android::AssetStreamAdaptor(asset)); SkMovie* moov = SkMovie::DecodeStream(stream.get()); return create_jmovie(env, moov); } static jobject movie_decodeStream(JNIEnv* env, jobject clazz, jobject istream) { NPE_CHECK_RETURN_ZERO(env, istream); SkStreamRewindable* strm = CheckForAssetStream(env, istream); jbyteArray byteArray = NULL; ScopedLocalRef<jbyteArray> scoper(env, NULL); if (NULL == strm) { byteArray = env->NewByteArray(16*1024); scoper.reset(byteArray); strm = GetRewindableStream(env, istream, byteArray); } jbyteArray byteArray = env->NewByteArray(16*1024); ScopedLocalRef<jbyteArray> scoper(env, byteArray); SkStream* strm = CreateJavaInputStreamAdaptor(env, istream, byteArray); if (NULL == strm) { return 0; } SkMovie* moov = SkMovie::DecodeStream(strm); // Need to buffer enough input to be able to rewind as much as might be read by a decoder // trying to determine the stream's format. The only decoder for movies is GIF, which // will only read 6. // FIXME: Get this number from SkImageDecoder SkAutoTUnref<SkStreamRewindable> bufferedStream(SkFrontBufferedStream::Create(strm, 6)); SkASSERT(bufferedStream.get() != NULL); SkMovie* moov = SkMovie::DecodeStream(bufferedStream); strm->unref(); return create_jmovie(env, moov); } Loading Loading @@ -135,7 +146,9 @@ static JNINativeMethod gMethods[] = { { "setTime", "(I)Z", (void*)movie_setTime }, { "draw", "(Landroid/graphics/Canvas;FFLandroid/graphics/Paint;)V", (void*)movie_draw }, { "decodeStream", "(Ljava/io/InputStream;)Landroid/graphics/Movie;", { "nativeDecodeAsset", "(I)Landroid/graphics/Movie;", (void*)movie_decodeAsset }, { "nativeDecodeStream", "(Ljava/io/InputStream;)Landroid/graphics/Movie;", (void*)movie_decodeStream }, { "nativeDestructor","(I)V", (void*)movie_destructor }, { "decodeByteArray", "([BII)Landroid/graphics/Movie;", Loading
graphics/java/android/graphics/BitmapFactory.java +14 −10 Original line number Diff line number Diff line Loading @@ -569,10 +569,7 @@ public class BitmapFactory { final int asset = ((AssetManager.AssetInputStream) is).getAssetInt(); bm = nativeDecodeAsset(asset, outPadding, opts); } else { byte [] tempStorage = null; if (opts != null) tempStorage = opts.inTempStorage; if (tempStorage == null) tempStorage = new byte[DECODE_BUFFER_SIZE]; bm = nativeDecodeStream(is, tempStorage, outPadding, opts); bm = decodeStreamInternal(is, outPadding, opts); } if (bm == null && opts != null && opts.inBitmap != null) { Loading @@ -587,6 +584,18 @@ public class BitmapFactory { return bm; } /** * Private helper function for decoding an InputStream natively. Buffers the input enough to * do a rewind as needed, and supplies temporary storage if necessary. is MUST NOT be null. */ private static Bitmap decodeStreamInternal(InputStream is, Rect outPadding, Options opts) { // ASSERT(is != null); byte [] tempStorage = null; if (opts != null) tempStorage = opts.inTempStorage; if (tempStorage == null) tempStorage = new byte[DECODE_BUFFER_SIZE]; return nativeDecodeStream(is, tempStorage, outPadding, opts); } /** * Decode an input stream into a bitmap. If the input stream is null, or * cannot be used to decode a bitmap, the function returns null. Loading Loading @@ -624,13 +633,8 @@ public class BitmapFactory { bm = nativeDecodeFileDescriptor(fd, outPadding, opts); } else { FileInputStream fis = new FileInputStream(fd); // FIXME: If nativeDecodeStream grabbed the pointer to tempStorage // from Options, this code would not need to be duplicated. byte [] tempStorage = null; if (opts != null) tempStorage = opts.inTempStorage; if (tempStorage == null) tempStorage = new byte[DECODE_BUFFER_SIZE]; try { bm = nativeDecodeStream(fis, tempStorage, outPadding, opts); bm = decodeStreamInternal(fis, outPadding, opts); } finally { try { fis.close(); Loading