diff options
author | Chet Haase <chet@google.com> | 2012-04-27 14:17:16 -0700 |
---|---|---|
committer | Chet Haase <chet@google.com> | 2012-04-30 11:17:57 -0700 |
commit | c0b4fa78738acf9ad587eb9fcbc2021be9a3ee77 (patch) | |
tree | cfa29d0525ea411ad3460c11e5c238352c5ab023 | |
parent | f98d96e192db421eed54103eedfcbb6600f73c08 (diff) | |
download | external_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.cpp | 12 | ||||
-rw-r--r-- | src/images/SkImageDecoder_libgif.cpp | 12 | ||||
-rw-r--r-- | src/images/SkImageDecoder_libico.cpp | 10 | ||||
-rw-r--r-- | src/images/SkImageDecoder_libwebp.cpp | 19 | ||||
-rw-r--r-- | src/images/SkImageDecoder_wbmp.cpp | 17 |
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); |