Allow bitmap reuse with PNG decoding

Change-Id: I8ba53eb6d4b99ce6352358b666d30b7668aa834f
diff --git a/include/core/SkTemplates.h b/include/core/SkTemplates.h
index 27ebd41..d484389 100644
--- a/include/core/SkTemplates.h
+++ b/include/core/SkTemplates.h
@@ -61,8 +61,10 @@
 
 template <typename T> class SkAutoTDelete : SkNoncopyable {
 public:
-    SkAutoTDelete(T* obj) : fObj(obj) {}
-    ~SkAutoTDelete() { delete fObj; }
+    SkAutoTDelete(T* obj, bool deleteWhenDone = true) : fObj(obj) {
+        this->deleteWhenDone = deleteWhenDone;
+    }
+    ~SkAutoTDelete() { if (deleteWhenDone) delete fObj; }
 
     T*      get() const { return fObj; }
     void    free() { delete fObj; fObj = NULL; }
@@ -70,6 +72,7 @@
 
 private:
     T*  fObj;
+    bool deleteWhenDone;
 };
 
 template <typename T> class SkAutoTDeleteArray : SkNoncopyable {
diff --git a/src/images/SkImageDecoder_libjpeg.cpp b/src/images/SkImageDecoder_libjpeg.cpp
index 358861e..514118d 100644
--- a/src/images/SkImageDecoder_libjpeg.cpp
+++ b/src/images/SkImageDecoder_libjpeg.cpp
@@ -328,8 +328,12 @@
         bm->lockPixels();
         JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels();
         bm->unlockPixels();
-        bool reuseBitmap = (rowptr != NULL && (int) cinfo.output_width == bm->width() &&
-                (int) cinfo.output_height == bm->height());
+        bool reuseBitmap = (rowptr != NULL);
+        if (reuseBitmap && ((int) cinfo.output_width != bm->width() ||
+                (int) cinfo.output_height != bm->height())) {
+            // Dimensions must match
+            return false;
+        }
 
         if (!reuseBitmap) {
             bm->setConfig(config, cinfo.output_width, cinfo.output_height);
@@ -389,9 +393,13 @@
 
     bm->lockPixels();
     JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels();
-    bool reuseBitmap = (rowptr != NULL && sampler.scaledWidth() == bm->width() &&
-            sampler.scaledHeight() == bm->height());
+    bool reuseBitmap = (rowptr != NULL);
     bm->unlockPixels();
+    if (reuseBitmap && (sampler.scaledWidth() != bm->width() ||
+            sampler.scaledHeight() != bm->height())) {
+        // Dimensions must match
+        return false;
+    }
 
     if (!reuseBitmap) {
         bm->setConfig(config, sampler.scaledWidth(), sampler.scaledHeight());
@@ -447,6 +455,9 @@
                        cinfo.output_height - cinfo.output_scanline)) {
         return return_false(cinfo, *bm, "skip rows");
     }
+    if (reuseBitmap) {
+        bm->notifyPixelsChanged();
+    }
     jpeg_finish_decompress(&cinfo);
 
 //    SkDebugf("------------------- bm2 size %d [%d %d] %d\n", bm->getSize(), bm->width(), bm->height(), bm->config());
diff --git a/src/images/SkImageDecoder_libpng.cpp b/src/images/SkImageDecoder_libpng.cpp
index e550767..5cd86f7 100644
--- a/src/images/SkImageDecoder_libpng.cpp
+++ b/src/images/SkImageDecoder_libpng.cpp
@@ -291,8 +291,20 @@
     const int sampleSize = this->getSampleSize();
     SkScaledBitmapSampler sampler(origWidth, origHeight, sampleSize);
 
-    decodedBitmap->setConfig(config, sampler.scaledWidth(),
-                             sampler.scaledHeight(), 0);
+    decodedBitmap->lockPixels();
+    void* rowptr = (void*) decodedBitmap->getPixels();
+    bool reuseBitmap = (rowptr != NULL);
+    decodedBitmap->unlockPixels();
+    if (reuseBitmap && (sampler.scaledWidth() != decodedBitmap->width() ||
+            sampler.scaledHeight() != decodedBitmap->height())) {
+        // Dimensions must match
+        return false;
+    }
+
+    if (!reuseBitmap) {
+        decodedBitmap->setConfig(config, sampler.scaledWidth(),
+                                 sampler.scaledHeight(), 0);
+    }
     if (SkImageDecoder::kDecodeBounds_Mode == mode) {
         return true;
     }
@@ -312,10 +324,12 @@
 
     SkAutoUnref aur(colorTable);
 
-    if (!this->allocPixelRef(decodedBitmap,
-                             SkBitmap::kIndex8_Config == config ?
-                                colorTable : NULL)) {
-        return false;
+    if (!reuseBitmap) {
+        if (!this->allocPixelRef(decodedBitmap,
+                                 SkBitmap::kIndex8_Config == config ?
+                                    colorTable : NULL)) {
+            return false;
+        }
     }
 
     SkAutoLockPixels alp(*decodedBitmap);
@@ -416,6 +430,9 @@
         reallyHasAlpha |= substituteTranspColor(decodedBitmap, theTranspColor);
     }
     decodedBitmap->setIsOpaque(!reallyHasAlpha);
+    if (reuseBitmap) {
+        decodedBitmap->notifyPixelsChanged();
+    }
     return true;
 }
 
@@ -684,7 +701,7 @@
     png_ptr->pass = 0;
     png_read_update_info(png_ptr, info_ptr);
 
-    SkDebugf("Request size %d %d\n", requestedWidth, requestedHeight);
+    // SkDebugf("Request size %d %d\n", requestedWidth, requestedHeight);
 
     int actualTop = rect.fTop;