Loading core/jni/android/graphics/BitmapFactory.cpp +64 −36 Original line number Original line Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include <utils/ResourceTypes.h> #include <utils/ResourceTypes.h> #include <netinet/in.h> #include <netinet/in.h> #include <sys/mman.h> #include <sys/mman.h> #include <sys/stat.h> jclass gOptions_class; jclass gOptions_class; jfieldID gOptions_justBoundsFieldID; jfieldID gOptions_justBoundsFieldID; Loading Loading @@ -559,7 +560,27 @@ static void nativeSetDefaultConfig(JNIEnv* env, jobject, int nativeConfig) { } } } } static jobject doBuildTileIndex(JNIEnv* env, SkStream* stream, bool isShareable) { static SkMemoryStream* buildSkMemoryStream(SkStream *stream) { size_t bufferSize = 4096; size_t streamLen = 0; size_t len; char* data = (char*)sk_malloc_throw(bufferSize); while ((len = stream->read(data + streamLen, bufferSize - streamLen)) != 0) { streamLen += len; if (streamLen == bufferSize) { bufferSize *= 2; data = (char*)sk_realloc_throw(data, bufferSize); } } data = (char*)sk_realloc_throw(data, streamLen); SkMemoryStream* streamMem = new SkMemoryStream(); streamMem->setMemoryOwned(data, streamLen); return streamMem; } static jobject doBuildTileIndex(JNIEnv* env, SkStream* stream) { SkImageDecoder* decoder = SkImageDecoder::Factory(stream); SkImageDecoder* decoder = SkImageDecoder::Factory(stream); int width, height; int width, height; if (NULL == decoder) { if (NULL == decoder) { Loading @@ -574,9 +595,10 @@ static jobject doBuildTileIndex(JNIEnv* env, SkStream* stream, bool isShareable) javaAllocator->unref(); javaAllocator->unref(); javaMemoryReporter->unref(); javaMemoryReporter->unref(); if (!decoder->buildTileIndex(stream, &width, &height, isShareable)) { if (!decoder->buildTileIndex(stream, &width, &height)) { char msg[1024]; char msg[100]; snprintf(msg, 1023, "Image failed to decode using %s decoder", decoder->getFormatName()); snprintf(msg, sizeof(msg), "Image failed to decode using %s decoder", decoder->getFormatName()); doThrowIOE(env, msg); doThrowIOE(env, msg); return nullObjectReturn("decoder->buildTileIndex returned false"); return nullObjectReturn("decoder->buildTileIndex returned false"); } } Loading @@ -588,13 +610,13 @@ static jobject doBuildTileIndex(JNIEnv* env, SkStream* stream, bool isShareable) static jobject nativeCreateLargeBitmapFromByteArray(JNIEnv* env, jobject, jbyteArray byteArray, static jobject nativeCreateLargeBitmapFromByteArray(JNIEnv* env, jobject, jbyteArray byteArray, int offset, int length, jboolean isShareable) { int offset, int length, jboolean isShareable) { /* If isShareable we could decide to just wrap the java array and share it, but that means adding a globalref to the java array object For now we just always copy the array's data if isShareable. */ AutoJavaByteArray ar(env, byteArray); AutoJavaByteArray ar(env, byteArray); SkStream* stream = new SkMemoryStream(ar.ptr() + offset, length, false); SkStream* stream = new SkMemoryStream(ar.ptr() + offset, length, true); SkAutoUnref aur(stream); return doBuildTileIndex(env, stream); if (isShareable) { aur.detach(); } return doBuildTileIndex(env, stream, isShareable); } } static jobject nativeCreateLargeBitmapFromFileDescriptor(JNIEnv* env, jobject clazz, static jobject nativeCreateLargeBitmapFromFileDescriptor(JNIEnv* env, jobject clazz, Loading @@ -603,24 +625,31 @@ static jobject nativeCreateLargeBitmapFromFileDescriptor(JNIEnv* env, jobject cl jint descriptor = env->GetIntField(fileDescriptor, jint descriptor = env->GetIntField(fileDescriptor, gFileDescriptor_descriptor); gFileDescriptor_descriptor); bool weOwnTheFD = false; SkStream *stream = NULL; struct stat fdStat; if (isShareable) { int newFD; int newFD = ::dup(descriptor); if (fstat(descriptor, &fdStat) == -1) { if (-1 != newFD) { doThrowIOE(env, "broken file descriptor"); weOwnTheFD = true; return nullObjectReturn("fstat return -1"); descriptor = newFD; } } if (isShareable && S_ISREG(fdStat.st_mode) && (newFD = ::dup(descriptor)) != -1) { SkFDStream* fdStream = new SkFDStream(newFD, true); if (!fdStream->isValid()) { fdStream->unref(); return NULL; } } stream = fdStream; SkFDStream* stream = new SkFDStream(descriptor, weOwnTheFD); } else { SkAutoUnref aur(stream); SkFDStream* fdStream = new SkFDStream(descriptor, false); if (!stream->isValid()) { if (!fdStream->isValid()) { fdStream->unref(); return NULL; return NULL; } } stream = buildSkMemoryStream(fdStream); if (isShareable) { fdStream->unref(); aur.detach(); } } /* Restore our offset when we leave, so we can be called more than once /* Restore our offset when we leave, so we can be called more than once Loading @@ -629,7 +658,7 @@ static jobject nativeCreateLargeBitmapFromFileDescriptor(JNIEnv* env, jobject cl */ */ AutoFDSeek as(descriptor); AutoFDSeek as(descriptor); return doBuildTileIndex(env, stream, isShareable); return doBuildTileIndex(env, stream); } } static jobject nativeCreateLargeBitmapFromStream(JNIEnv* env, jobject clazz, static jobject nativeCreateLargeBitmapFromStream(JNIEnv* env, jobject clazz, Loading @@ -641,7 +670,8 @@ static jobject nativeCreateLargeBitmapFromStream(JNIEnv* env, jobject clazz, if (stream) { if (stream) { // for now we don't allow shareable with java inputstreams // for now we don't allow shareable with java inputstreams largeBitmap = doBuildTileIndex(env, stream, false); SkMemoryStream *mStream = buildSkMemoryStream(stream); largeBitmap = doBuildTileIndex(env, mStream); stream->unref(); stream->unref(); } } return largeBitmap; return largeBitmap; Loading @@ -650,14 +680,12 @@ static jobject nativeCreateLargeBitmapFromStream(JNIEnv* env, jobject clazz, static jobject nativeCreateLargeBitmapFromAsset(JNIEnv* env, jobject clazz, static jobject nativeCreateLargeBitmapFromAsset(JNIEnv* env, jobject clazz, jint native_asset, // Asset jint native_asset, // Asset jboolean isShareable) { jboolean isShareable) { SkStream* stream; SkStream* stream, *assStream; Asset* asset = reinterpret_cast<Asset*>(native_asset); Asset* asset = reinterpret_cast<Asset*>(native_asset); stream = new AssetStreamAdaptor(asset); assStream = new AssetStreamAdaptor(asset); SkAutoUnref aur(stream); stream = buildSkMemoryStream(assStream); if (isShareable) { assStream->unref(); aur.detach(); return doBuildTileIndex(env, stream); } return doBuildTileIndex(env, stream, isShareable); } } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// Loading Loading
core/jni/android/graphics/BitmapFactory.cpp +64 −36 Original line number Original line Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include <utils/ResourceTypes.h> #include <utils/ResourceTypes.h> #include <netinet/in.h> #include <netinet/in.h> #include <sys/mman.h> #include <sys/mman.h> #include <sys/stat.h> jclass gOptions_class; jclass gOptions_class; jfieldID gOptions_justBoundsFieldID; jfieldID gOptions_justBoundsFieldID; Loading Loading @@ -559,7 +560,27 @@ static void nativeSetDefaultConfig(JNIEnv* env, jobject, int nativeConfig) { } } } } static jobject doBuildTileIndex(JNIEnv* env, SkStream* stream, bool isShareable) { static SkMemoryStream* buildSkMemoryStream(SkStream *stream) { size_t bufferSize = 4096; size_t streamLen = 0; size_t len; char* data = (char*)sk_malloc_throw(bufferSize); while ((len = stream->read(data + streamLen, bufferSize - streamLen)) != 0) { streamLen += len; if (streamLen == bufferSize) { bufferSize *= 2; data = (char*)sk_realloc_throw(data, bufferSize); } } data = (char*)sk_realloc_throw(data, streamLen); SkMemoryStream* streamMem = new SkMemoryStream(); streamMem->setMemoryOwned(data, streamLen); return streamMem; } static jobject doBuildTileIndex(JNIEnv* env, SkStream* stream) { SkImageDecoder* decoder = SkImageDecoder::Factory(stream); SkImageDecoder* decoder = SkImageDecoder::Factory(stream); int width, height; int width, height; if (NULL == decoder) { if (NULL == decoder) { Loading @@ -574,9 +595,10 @@ static jobject doBuildTileIndex(JNIEnv* env, SkStream* stream, bool isShareable) javaAllocator->unref(); javaAllocator->unref(); javaMemoryReporter->unref(); javaMemoryReporter->unref(); if (!decoder->buildTileIndex(stream, &width, &height, isShareable)) { if (!decoder->buildTileIndex(stream, &width, &height)) { char msg[1024]; char msg[100]; snprintf(msg, 1023, "Image failed to decode using %s decoder", decoder->getFormatName()); snprintf(msg, sizeof(msg), "Image failed to decode using %s decoder", decoder->getFormatName()); doThrowIOE(env, msg); doThrowIOE(env, msg); return nullObjectReturn("decoder->buildTileIndex returned false"); return nullObjectReturn("decoder->buildTileIndex returned false"); } } Loading @@ -588,13 +610,13 @@ static jobject doBuildTileIndex(JNIEnv* env, SkStream* stream, bool isShareable) static jobject nativeCreateLargeBitmapFromByteArray(JNIEnv* env, jobject, jbyteArray byteArray, static jobject nativeCreateLargeBitmapFromByteArray(JNIEnv* env, jobject, jbyteArray byteArray, int offset, int length, jboolean isShareable) { int offset, int length, jboolean isShareable) { /* If isShareable we could decide to just wrap the java array and share it, but that means adding a globalref to the java array object For now we just always copy the array's data if isShareable. */ AutoJavaByteArray ar(env, byteArray); AutoJavaByteArray ar(env, byteArray); SkStream* stream = new SkMemoryStream(ar.ptr() + offset, length, false); SkStream* stream = new SkMemoryStream(ar.ptr() + offset, length, true); SkAutoUnref aur(stream); return doBuildTileIndex(env, stream); if (isShareable) { aur.detach(); } return doBuildTileIndex(env, stream, isShareable); } } static jobject nativeCreateLargeBitmapFromFileDescriptor(JNIEnv* env, jobject clazz, static jobject nativeCreateLargeBitmapFromFileDescriptor(JNIEnv* env, jobject clazz, Loading @@ -603,24 +625,31 @@ static jobject nativeCreateLargeBitmapFromFileDescriptor(JNIEnv* env, jobject cl jint descriptor = env->GetIntField(fileDescriptor, jint descriptor = env->GetIntField(fileDescriptor, gFileDescriptor_descriptor); gFileDescriptor_descriptor); bool weOwnTheFD = false; SkStream *stream = NULL; struct stat fdStat; if (isShareable) { int newFD; int newFD = ::dup(descriptor); if (fstat(descriptor, &fdStat) == -1) { if (-1 != newFD) { doThrowIOE(env, "broken file descriptor"); weOwnTheFD = true; return nullObjectReturn("fstat return -1"); descriptor = newFD; } } if (isShareable && S_ISREG(fdStat.st_mode) && (newFD = ::dup(descriptor)) != -1) { SkFDStream* fdStream = new SkFDStream(newFD, true); if (!fdStream->isValid()) { fdStream->unref(); return NULL; } } stream = fdStream; SkFDStream* stream = new SkFDStream(descriptor, weOwnTheFD); } else { SkAutoUnref aur(stream); SkFDStream* fdStream = new SkFDStream(descriptor, false); if (!stream->isValid()) { if (!fdStream->isValid()) { fdStream->unref(); return NULL; return NULL; } } stream = buildSkMemoryStream(fdStream); if (isShareable) { fdStream->unref(); aur.detach(); } } /* Restore our offset when we leave, so we can be called more than once /* Restore our offset when we leave, so we can be called more than once Loading @@ -629,7 +658,7 @@ static jobject nativeCreateLargeBitmapFromFileDescriptor(JNIEnv* env, jobject cl */ */ AutoFDSeek as(descriptor); AutoFDSeek as(descriptor); return doBuildTileIndex(env, stream, isShareable); return doBuildTileIndex(env, stream); } } static jobject nativeCreateLargeBitmapFromStream(JNIEnv* env, jobject clazz, static jobject nativeCreateLargeBitmapFromStream(JNIEnv* env, jobject clazz, Loading @@ -641,7 +670,8 @@ static jobject nativeCreateLargeBitmapFromStream(JNIEnv* env, jobject clazz, if (stream) { if (stream) { // for now we don't allow shareable with java inputstreams // for now we don't allow shareable with java inputstreams largeBitmap = doBuildTileIndex(env, stream, false); SkMemoryStream *mStream = buildSkMemoryStream(stream); largeBitmap = doBuildTileIndex(env, mStream); stream->unref(); stream->unref(); } } return largeBitmap; return largeBitmap; Loading @@ -650,14 +680,12 @@ static jobject nativeCreateLargeBitmapFromStream(JNIEnv* env, jobject clazz, static jobject nativeCreateLargeBitmapFromAsset(JNIEnv* env, jobject clazz, static jobject nativeCreateLargeBitmapFromAsset(JNIEnv* env, jobject clazz, jint native_asset, // Asset jint native_asset, // Asset jboolean isShareable) { jboolean isShareable) { SkStream* stream; SkStream* stream, *assStream; Asset* asset = reinterpret_cast<Asset*>(native_asset); Asset* asset = reinterpret_cast<Asset*>(native_asset); stream = new AssetStreamAdaptor(asset); assStream = new AssetStreamAdaptor(asset); SkAutoUnref aur(stream); stream = buildSkMemoryStream(assStream); if (isShareable) { assStream->unref(); aur.detach(); return doBuildTileIndex(env, stream); } return doBuildTileIndex(env, stream, isShareable); } } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// Loading