Fix bug in SkImageDecoder

Change-Id: I6d214e4d8cce49f7e12eeb924493161dadd5aa26
diff --git a/include/core/SkStream.h b/include/core/SkStream.h
index 3a82991..798c6be 100644
--- a/include/core/SkStream.h
+++ b/include/core/SkStream.h
@@ -176,6 +176,7 @@
     */
     virtual void setMemory(const void* data, size_t length,
                            bool copyData = false);
+    virtual void setMemoryOwned(const void* src, size_t size);
     void skipToAlign4();
     virtual bool rewind();
     virtual size_t read(void* buffer, size_t size);
diff --git a/include/images/SkImageDecoder.h b/include/images/SkImageDecoder.h
index a3d7f1d..767a09a 100644
--- a/include/images/SkImageDecoder.h
+++ b/include/images/SkImageDecoder.h
@@ -204,9 +204,7 @@
      * Return true for success or false on failure.
      */
     virtual bool buildTileIndex(SkStream*,
-                                int *width, int *height, bool isShareable) {
-        return false;
-    }
+                                int *width, int *height);
 
     /**
      * Decode a rectangle region in the image specified by rect.
@@ -307,7 +305,15 @@
     // must be overridden in subclasses. This guy is called by decode(...)
     virtual bool onDecode(SkStream*, SkBitmap* bitmap, Mode) = 0;
 
-    // must be overridden in subclasses. This guy is called by decodeRegion(...)
+    // If the decoder wants to support tiled based decoding,
+    // this method must be overridden. This guy is called by buildTileIndex(...)
+    virtual bool onBuildTileIndex(SkStream*,
+                int *width, int *height) {
+        return false;
+    }
+
+    // If the decoder wants to support tiled based decoding,
+    // this method must be overridden. This guy is called by decodeRegion(...)
     virtual bool onDecodeRegion(SkBitmap* bitmap, SkIRect rect) {
         return false;
     }
diff --git a/include/images/SkJpegUtility.h b/include/images/SkJpegUtility.h
index 5dd789c9..e9dd977 100644
--- a/include/images/SkJpegUtility.h
+++ b/include/images/SkJpegUtility.h
@@ -41,7 +41,7 @@
 /* Our source struct for directing jpeg to our stream object.
 */
 struct skjpeg_source_mgr : jpeg_source_mgr {
-    skjpeg_source_mgr(SkStream* stream, SkImageDecoder* decoder, bool copyStream, bool ownStream);
+    skjpeg_source_mgr(SkStream* stream, SkImageDecoder* decoder, bool ownStream);
     ~skjpeg_source_mgr();
 
     SkStream*   fStream;
diff --git a/src/core/SkStream.cpp b/src/core/SkStream.cpp
index 6187f81..6157105 100644
--- a/src/core/SkStream.cpp
+++ b/src/core/SkStream.cpp
@@ -265,6 +265,18 @@
         sk_free((void*)fSrc);
 }
 
+void SkMemoryStream::setMemoryOwned(const void* src, size_t size)
+{
+    if (fWeOwnTheData)
+        sk_free((void*)fSrc);
+
+    fSize = size;
+    fOffset = 0;
+    fWeOwnTheData = true;
+
+    fSrc = src;
+}
+
 void SkMemoryStream::setMemory(const void* src, size_t size, bool copyData)
 {
     if (fWeOwnTheData)
diff --git a/src/images/SkImageDecoder.cpp b/src/images/SkImageDecoder.cpp
index 8c57886..053caea 100644
--- a/src/images/SkImageDecoder.cpp
+++ b/src/images/SkImageDecoder.cpp
@@ -188,6 +188,14 @@
     return true;
 }
 
+bool SkImageDecoder::buildTileIndex(SkStream* stream,
+                                int *width, int *height) {
+    // we reset this to false before calling onBuildTileIndex
+    fShouldCancelDecode = false;
+
+    return this->onBuildTileIndex(stream, width, height);
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 bool SkImageDecoder::DecodeFile(const char file[], SkBitmap* bm,
diff --git a/src/images/SkImageDecoder_libjpeg.cpp b/src/images/SkImageDecoder_libjpeg.cpp
index 29c4b46..0565a3b 100644
--- a/src/images/SkImageDecoder_libjpeg.cpp
+++ b/src/images/SkImageDecoder_libjpeg.cpp
@@ -77,10 +77,10 @@
     virtual Format getFormat() const {
         return kJPEG_Format;
     }
-    virtual bool buildTileIndex(SkStream *stream,
-                                int *width, int *height, bool isShareable);
 
 protected:
+    virtual bool onBuildTileIndex(SkStream *stream,
+                                int *width, int *height);
     virtual bool onDecodeRegion(SkBitmap* bitmap, SkIRect rect);
     virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode);
     virtual void cropBitmap(SkBitmap *dest, SkBitmap *src, int sampleSize,
@@ -208,7 +208,7 @@
 
     jpeg_decompress_struct  cinfo;
     skjpeg_error_mgr        sk_err;
-    skjpeg_source_mgr       sk_stream(stream, this, false, false);
+    skjpeg_source_mgr       sk_stream(stream, this, false);
 
     cinfo.err = jpeg_std_error(&sk_err);
     sk_err.error_exit = skjpeg_error_exit;
@@ -433,9 +433,8 @@
     return true;
 }
 
-bool SkJPEGImageDecoder::buildTileIndex(SkStream* stream,
-                                        int *width, int *height,
-                                        bool isShareable) {
+bool SkJPEGImageDecoder::onBuildTileIndex(SkStream* stream,
+                                        int *width, int *height) {
     SkAutoMalloc  srcStorage;
     SkJPEGImageIndex *index = new SkJPEGImageIndex;
 
@@ -443,7 +442,7 @@
                                         malloc(sizeof(jpeg_decompress_struct));
     skjpeg_error_mgr        sk_err;
     skjpeg_source_mgr       *sk_stream =
-        new skjpeg_source_mgr(stream, this, !isShareable, true);
+        new skjpeg_source_mgr(stream, this, true);
     if (cinfo == NULL || sk_stream == NULL) {
         return false;
     }
diff --git a/src/images/SkJpegUtility.cpp b/src/images/SkJpegUtility.cpp
index ac65b9e..a2fe9a8 100644
--- a/src/images/SkJpegUtility.cpp
+++ b/src/images/SkJpegUtility.cpp
@@ -131,43 +131,21 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 skjpeg_source_mgr::skjpeg_source_mgr(SkStream* stream, SkImageDecoder* decoder,
-                                     bool copyStream, bool ownStream) : fStream(stream) {
+                                     bool ownStream) : fStream(stream) {
     fDecoder = decoder;
     const void* baseAddr = stream->getMemoryBase();
     size_t bufferSize = 4096;
     size_t len;
     fMemoryBase = NULL;
     fUnrefStream = ownStream;
-    if (copyStream) {
-        fMemoryBaseSize = 0;
-        fMemoryBase = sk_malloc_throw(bufferSize);
-        while ((len = stream->read((char*)fMemoryBase + fMemoryBaseSize,
-                    bufferSize - fMemoryBaseSize)) != 0) {
-            fMemoryBaseSize += len;
-            if (fMemoryBaseSize == bufferSize) {
-                bufferSize *= 2;
-                fMemoryBase = sk_realloc_throw(fMemoryBase, bufferSize);
-            }
-        }
-        fMemoryBase = sk_realloc_throw(fMemoryBase, fMemoryBaseSize);
+    fMemoryBaseSize = 0;
 
-        init_source = skmem_init_source;
-        fill_input_buffer = skmem_fill_input_buffer;
-        skip_input_data = skmem_skip_input_data;
-        resync_to_restart = skmem_resync_to_restart;
-        term_source = skmem_term_source;
-        seek_input_data = NULL;
-    } else {
-        fMemoryBase = NULL;
-        fMemoryBaseSize = 0;
-
-        init_source = sk_init_source;
-        fill_input_buffer = sk_fill_input_buffer;
-        skip_input_data = sk_skip_input_data;
-        resync_to_restart = sk_resync_to_restart;
-        term_source = sk_term_source;
-        seek_input_data = sk_seek_input_data;
-    }
+    init_source = sk_init_source;
+    fill_input_buffer = sk_fill_input_buffer;
+    skip_input_data = sk_skip_input_data;
+    resync_to_restart = sk_resync_to_restart;
+    term_source = sk_term_source;
+    seek_input_data = sk_seek_input_data;
 //    SkDebugf("**************** use memorybase %p %d\n", fMemoryBase, fMemoryBaseSize);
 }