am 219eb7ec: Merge "Fix bug in JNI BitmapFactory" into gingerbread

Merge commit '219eb7ec8403ef9b98125f2b58cc27669ae69712' into gingerbread-plus-aosp

* commit '219eb7ec8403ef9b98125f2b58cc27669ae69712':
  Fix bug in JNI BitmapFactory
This commit is contained in:
Joseph Wen
2010-09-10 02:35:50 -07:00
committed by Android Git Automerger
2 changed files with 63 additions and 41 deletions

View File

@@ -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;
@@ -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) {
@@ -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");
} }
@@ -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,
@@ -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;
int newFD;
if (fstat(descriptor, &fdStat) == -1) {
doThrowIOE(env, "broken file descriptor");
return nullObjectReturn("fstat return -1");
}
if (isShareable) { if (isShareable &&
int newFD = ::dup(descriptor); S_ISREG(fdStat.st_mode) &&
if (-1 != newFD) { (newFD = ::dup(descriptor)) != -1) {
weOwnTheFD = true; SkFDStream* fdStream = new SkFDStream(newFD, true);
descriptor = newFD; if (!fdStream->isValid()) {
fdStream->unref();
return NULL;
} }
} stream = fdStream;
} else {
SkFDStream* stream = new SkFDStream(descriptor, weOwnTheFD); SkFDStream* fdStream = new SkFDStream(descriptor, false);
SkAutoUnref aur(stream); if (!fdStream->isValid()) {
if (!stream->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
@@ -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,
@@ -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;
@@ -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);
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@@ -628,12 +628,6 @@ public class BitmapFactory {
*/ */
public static LargeBitmap createLargeBitmap( public static LargeBitmap createLargeBitmap(
FileDescriptor fd, boolean isShareable) throws IOException { FileDescriptor fd, boolean isShareable) throws IOException {
if (MemoryFile.isMemoryFile(fd)) {
int mappedlength = MemoryFile.getSize(fd);
MemoryFile file = new MemoryFile(fd, mappedlength, "r");
InputStream is = file.getInputStream();
return createLargeBitmap(is, isShareable);
}
return nativeCreateLargeBitmap(fd, isShareable); return nativeCreateLargeBitmap(fd, isShareable);
} }