add(decoder);
@@ -233,14 +245,14 @@ static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding,
// happens earlier than AutoDecoderCancel object is added
// to the gAutoDecoderCancelMutex linked list.
if (NULL != options && env->GetBooleanField(options, gOptions_mCancelID)) {
- return nullObjectReturn("gOptions_mCancelID");;
+ return nullObjectReturn("gOptions_mCancelID");
}
SkImageDecoder::Mode decodeMode = mode;
if (isPurgeable) {
decodeMode = SkImageDecoder::kDecodeBounds_Mode;
}
- if (!decoder->decode(stream, bitmap, prefConfig, decodeMode)) {
+ if (!decoder->decode(stream, bitmap, prefConfig, decodeMode, javaBitmap != NULL)) {
return nullObjectReturn("decoder->decode returned false");
}
@@ -301,6 +313,11 @@ static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding,
}
// promise we will never change our pixels (great for sharing and pictures)
pr->setImmutable();
+
+ if (javaBitmap != NULL) {
+ // If a java bitmap was passed in for reuse, pass it back
+ return javaBitmap;
+ }
// now create the java bitmap
return GraphicsJNI::createBitmap(env, bitmap, false, ninePatchChunk);
}
@@ -554,6 +571,8 @@ static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz,
int register_android_graphics_BitmapFactory(JNIEnv* env);
int register_android_graphics_BitmapFactory(JNIEnv* env) {
gOptions_class = make_globalref(env, "android/graphics/BitmapFactory$Options");
+ gOptions_bitmapFieldID = getFieldIDCheck(env, gOptions_class, "inBitmap",
+ "Landroid/graphics/Bitmap;");
gOptions_justBoundsFieldID = getFieldIDCheck(env, gOptions_class, "inJustDecodeBounds", "Z");
gOptions_sampleSizeFieldID = getFieldIDCheck(env, gOptions_class, "inSampleSize", "I");
gOptions_configFieldID = getFieldIDCheck(env, gOptions_class, "inPreferredConfig",
@@ -569,6 +588,8 @@ int register_android_graphics_BitmapFactory(JNIEnv* env) {
gOptions_mimeFieldID = getFieldIDCheck(env, gOptions_class, "outMimeType", "Ljava/lang/String;");
gOptions_mCancelID = getFieldIDCheck(env, gOptions_class, "mCancel", "Z");
+ gBitmap_class = make_globalref(env, "android/graphics/Bitmap");
+ gBitmap_nativeBitmapFieldID = getFieldIDCheck(env, gBitmap_class, "mNativeBitmap", "I");
gFileDescriptor_class = make_globalref(env, "java/io/FileDescriptor");
gFileDescriptor_descriptor = getFieldIDCheck(env, gFileDescriptor_class, "descriptor", "I");
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index 66f8f700a7854..f6a9c639699f8 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -42,6 +42,26 @@ public class BitmapFactory {
inScaled = true;
}
+ /**
+ * If set, decode methods that take the Options object will attempt to
+ * reuse this bitmap when loading content. This is a hint to the decoder
+ * only, and the decoder may choose to create a new Bitmap instead. The
+ * current implementation necessitates that the reused bitmap be of the
+ * same size as the source content and in jpeg format (whether as a
+ * resource or as a stream). The {@link android.graphics.Bitmap.Config
+ * configuration} of the reused bitmap will override the setting of
+ * {@link #inPreferredConfig}, if set.
+ *
+ * You should still always use the returned Bitmap of the decode
+ * method and not assume that reusing the bitmap worked, due to the
+ * constraints outlined above and failure situations that can occur.
+ * Checking whether the return value matches the value of the inBitmap
+ * set in the Options structure is a way to see if the bitmap was reused,
+ * but in all cases you should use the returned Bitmap to make sure
+ * that you are using the bitmap that was used as the decode destination.
+ */
+ public Bitmap inBitmap;
+
/**
* If set to true, the decoder will return null (no bitmap), but
* the out... fields will still be set, allowing the caller to query