aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChet Haase <chet@google.com>2012-04-27 14:17:16 -0700
committerChet Haase <chet@google.com>2012-04-30 11:17:57 -0700
commitc0b4fa78738acf9ad587eb9fcbc2021be9a3ee77 (patch)
treecfa29d0525ea411ad3460c11e5c238352c5ab023
parentf98d96e192db421eed54103eedfcbb6600f73c08 (diff)
downloadexternal_skia-c0b4fa78738acf9ad587eb9fcbc2021be9a3ee77.zip
external_skia-c0b4fa78738acf9ad587eb9fcbc2021be9a3ee77.tar.gz
external_skia-c0b4fa78738acf9ad587eb9fcbc2021be9a3ee77.tar.bz2
Handle Bitmap reuse failure more gracefully
A feature in Android 3.0 allows Bitmaps to be reused when loading a bitmap of the same dimensions. A documented limitation is that the only formats supported are jpeg and png, the most common formats for Android. But if you actually try to do it anyway, you'll end up causing memory trashing and an eventual strange native crash. It's not pretty. This fix puts code in other possible image format decoders (gif, ico, and bmp) to return false from the onDecode() operation, which will result in an exception being thrown back to the user code. Issue #6146246 Sparodic crash in GraphicsJNI::allocateJavaPixelRef (memory corruption?) Change-Id: Ifd3e0f87c9ea6d41a37f58616e1ced0b19132056
-rw-r--r--src/images/SkImageDecoder_libbmp.cpp12
-rw-r--r--src/images/SkImageDecoder_libgif.cpp12
-rw-r--r--src/images/SkImageDecoder_libico.cpp10
-rw-r--r--src/images/SkImageDecoder_libwebp.cpp19
-rw-r--r--src/images/SkImageDecoder_wbmp.cpp17
5 files changed, 55 insertions, 15 deletions
diff --git a/src/images/SkImageDecoder_libbmp.cpp b/src/images/SkImageDecoder_libbmp.cpp
index b5e49e8..6f82def 100644
--- a/src/images/SkImageDecoder_libbmp.cpp
+++ b/src/images/SkImageDecoder_libbmp.cpp
@@ -111,11 +111,19 @@ bool SkBMPImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
SkScaledBitmapSampler sampler(width, height, getSampleSize());
- bm->setConfig(config, sampler.scaledWidth(), sampler.scaledHeight());
- bm->setIsOpaque(true);
if (justBounds) {
+ bm->setConfig(config, sampler.scaledWidth(), sampler.scaledHeight());
+ bm->setIsOpaque(true);
return true;
}
+#ifdef SK_BUILD_FOR_ANDROID
+ // No Bitmap reuse supported for this format
+ if (!bm->isNull()) {
+ return false;
+ }
+#endif
+ bm->setConfig(config, sampler.scaledWidth(), sampler.scaledHeight());
+ bm->setIsOpaque(true);
if (!this->allocPixelRef(bm, NULL)) {
return false;
diff --git a/src/images/SkImageDecoder_libgif.cpp b/src/images/SkImageDecoder_libgif.cpp
index 7a451a0..2975478 100644
--- a/src/images/SkImageDecoder_libgif.cpp
+++ b/src/images/SkImageDecoder_libgif.cpp
@@ -191,10 +191,18 @@ bool SkGIFImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* bm, Mode mode) {
return error_return(gif, *bm, "chooseFromOneChoice");
}
- bm->setConfig(SkBitmap::kIndex8_Config, width, height);
- if (SkImageDecoder::kDecodeBounds_Mode == mode)
+ if (SkImageDecoder::kDecodeBounds_Mode == mode) {
+ bm->setConfig(SkBitmap::kIndex8_Config, width, height);
return true;
+ }
+#ifdef SK_BUILD_FOR_ANDROID
+ // No Bitmap reuse supported for this format
+ if (!bm->isNull()) {
+ return false;
+ }
+#endif
+ bm->setConfig(SkBitmap::kIndex8_Config, width, height);
SavedImage* image = &gif->SavedImages[gif->ImageCount-1];
const GifImageDesc& desc = image->ImageDesc;
diff --git a/src/images/SkImageDecoder_libico.cpp b/src/images/SkImageDecoder_libico.cpp
index bb6bc95..25a5078 100644
--- a/src/images/SkImageDecoder_libico.cpp
+++ b/src/images/SkImageDecoder_libico.cpp
@@ -234,12 +234,18 @@ bool SkICOImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode)
//if the andbitmap (mask) is all zeroes, then we can easily do an index bitmap
//however, with small images with large colortables, maybe it's better to still do argb_8888
- bm->setConfig(SkBitmap::kARGB_8888_Config, w, h, calculateRowBytesFor8888(w, bitCount));
-
if (SkImageDecoder::kDecodeBounds_Mode == mode) {
+ bm->setConfig(SkBitmap::kARGB_8888_Config, w, h, calculateRowBytesFor8888(w, bitCount));
delete[] colors;
return true;
}
+#ifdef SK_BUILD_FOR_ANDROID
+ // No Bitmap reuse supported for this format
+ if (!bm->isNull()) {
+ return false;
+ }
+#endif
+ bm->setConfig(SkBitmap::kARGB_8888_Config, w, h, calculateRowBytesFor8888(w, bitCount));
if (!this->allocPixelRef(bm, NULL))
{
diff --git a/src/images/SkImageDecoder_libwebp.cpp b/src/images/SkImageDecoder_libwebp.cpp
index 984331c..c2fce45 100644
--- a/src/images/SkImageDecoder_libwebp.cpp
+++ b/src/images/SkImageDecoder_libwebp.cpp
@@ -352,15 +352,24 @@ bool SkWEBPImageDecoder::onDecode(SkStream* stream, SkBitmap* decodedBitmap,
const int sampleSize = this->getSampleSize();
SkScaledBitmapSampler sampler(origWidth, origHeight, sampleSize);
- if (!setDecodeConfig(decodedBitmap, sampler.scaledWidth(),
- sampler.scaledHeight())) {
- return false;
- }
-
// If only bounds are requested, done
if (SkImageDecoder::kDecodeBounds_Mode == mode) {
+ if (!setDecodeConfig(decodedBitmap, sampler.scaledWidth(),
+ sampler.scaledHeight())) {
+ return false;
+ }
return true;
}
+#ifdef SK_BUILD_FOR_ANDROID
+ // No Bitmap reuse supported for this format
+ if (!decodedBitmap->isNull()) {
+ return false;
+ }
+#endif
+ if (!setDecodeConfig(decodedBitmap, sampler.scaledWidth(),
+ sampler.scaledHeight())) {
+ return false;
+ }
if (!this->allocPixelRef(decodedBitmap, NULL)) {
return return_false(*decodedBitmap, "allocPixelRef");
diff --git a/src/images/SkImageDecoder_wbmp.cpp b/src/images/SkImageDecoder_wbmp.cpp
index a7d910f..1ec82d9 100644
--- a/src/images/SkImageDecoder_wbmp.cpp
+++ b/src/images/SkImageDecoder_wbmp.cpp
@@ -110,13 +110,22 @@ bool SkWBMPImageDecoder::onDecode(SkStream* stream, SkBitmap* decodedBitmap,
int width = head.fWidth;
int height = head.fHeight;
+ if (SkImageDecoder::kDecodeBounds_Mode == mode) {
+ // assign these directly, in case we return kDimensions_Result
+ decodedBitmap->setConfig(SkBitmap::kIndex8_Config, width, height);
+ decodedBitmap->setIsOpaque(true);
+ return true;
+ }
+#ifdef SK_BUILD_FOR_ANDROID
+ // No Bitmap reuse supported for this format
+ if (!decodedBitmap->isNull()) {
+ return false;
+ }
+#endif
// assign these directly, in case we return kDimensions_Result
decodedBitmap->setConfig(SkBitmap::kIndex8_Config, width, height);
decodedBitmap->setIsOpaque(true);
-
- if (SkImageDecoder::kDecodeBounds_Mode == mode)
- return true;
-
+
const SkPMColor colors[] = { SK_ColorBLACK, SK_ColorWHITE };
SkColorTable* ct = SkNEW_ARGS(SkColorTable, (colors, 2));
SkAutoUnref aur(ct);