Change SkImageDecoders to take an SkStreamRewindable.

Only affects factories, static functions that will use the factories,
and subset decoding, which all require rewinding. The decoders
themselves continue to take an SkStream. This is merely documentation
stating which functions will possibly rewind the passed in SkStream.

This is part of the general change to coordinate SkStreams with
Android's streams, which don't necessarily support rewinding in all
cases.

Update callers to use SkStreamRewindable.

BUG=skia:1572
R=bungeman@google.com, reed@google.com

Review URL: https://codereview.chromium.org/23477009

git-svn-id: http://skia.googlecode.com/svn/trunk@11460 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/core/SkImageDecoder.h b/include/core/SkImageDecoder.h
index a8cbe63..bff7495 100644
--- a/include/core/SkImageDecoder.h
+++ b/include/core/SkImageDecoder.h
@@ -19,6 +19,7 @@
 #include "SkTypes.h"
 
 class SkStream;
+class SkStreamRewindable;
 
 /** \class SkImageDecoder
 
@@ -46,10 +47,10 @@
     */
     virtual Format getFormat() const;
 
-    /** Return the format of the SkStream or kUnknown_Format if it cannot be determined. Rewinds the
-        stream before returning.
+    /** Return the format of the SkStreamRewindable or kUnknown_Format if it cannot be determined.
+        Rewinds the stream before returning.
     */
-    static Format GetStreamFormat(SkStream*);
+    static Format GetStreamFormat(SkStreamRewindable*);
 
     /** Return a readable string of the Format provided.
     */
@@ -290,7 +291,7 @@
      *
      * Return true for success or false on failure.
      */
-    bool buildTileIndex(SkStream*, int *width, int *height);
+    bool buildTileIndex(SkStreamRewindable*, int *width, int *height);
 
     /**
      * Decode a rectangle subset in the image.
@@ -312,7 +313,7 @@
     /** Given a stream, this will try to find an appropriate decoder object.
         If none is found, the method returns NULL.
     */
-    static SkImageDecoder* Factory(SkStream*);
+    static SkImageDecoder* Factory(SkStreamRewindable*);
 
     /** Decode the image stored in the specified file, and store the result
         in bitmap. Return true for success or false on failure.
@@ -374,7 +375,7 @@
     static bool DecodeMemoryToTarget(const void* buffer, size_t size, SkImage::Info* info,
                                      const SkBitmapFactory::Target* target);
 
-    /** Decode the image stored in the specified SkStream, and store the result
+    /** Decode the image stored in the specified SkStreamRewindable, and store the result
         in bitmap. Return true for success or false on failure.
 
         @param prefConfig If the PrefConfigTable is not set, prefer this config.
@@ -383,10 +384,10 @@
         @param format On success, if format is non-null, it is set to the format
                       of the decoded stream. On failure it is ignored.
      */
-    static bool DecodeStream(SkStream* stream, SkBitmap* bitmap,
+    static bool DecodeStream(SkStreamRewindable* stream, SkBitmap* bitmap,
                              SkBitmap::Config prefConfig, Mode,
                              Format* format = NULL);
-    static bool DecodeStream(SkStream* stream, SkBitmap* bitmap) {
+    static bool DecodeStream(SkStreamRewindable* stream, SkBitmap* bitmap) {
         return DecodeStream(stream, bitmap, SkBitmap::kNo_Config,
                             kDecodePixels_Mode, NULL);
     }
@@ -411,7 +412,7 @@
 
     // 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) {
+    virtual bool onBuildTileIndex(SkStreamRewindable*, int *width, int *height) {
         return false;
     }
 
@@ -522,7 +523,7 @@
 public:
     SK_DECLARE_INST_COUNT(SkImageDecoderFactory)
 
-    virtual SkImageDecoder* newDecoder(SkStream*) = 0;
+    virtual SkImageDecoder* newDecoder(SkStreamRewindable*) = 0;
 
 private:
     typedef SkRefCnt INHERITED;
@@ -531,7 +532,7 @@
 class SkDefaultImageDecoderFactory : SkImageDecoderFactory {
 public:
     // calls SkImageDecoder::Factory(stream)
-    virtual SkImageDecoder* newDecoder(SkStream* stream) {
+    virtual SkImageDecoder* newDecoder(SkStreamRewindable* stream) {
         return SkImageDecoder::Factory(stream);
     }
 };
@@ -561,7 +562,7 @@
 
 // Typedefs to make registering decoder and formatter callbacks easier.
 // These have to be defined outside SkImageDecoder. :(
-typedef SkTRegistry<SkImageDecoder*(*)(SkStream*)>        SkImageDecoder_DecodeReg;
-typedef SkTRegistry<SkImageDecoder::Format(*)(SkStream*)> SkImageDecoder_FormatReg;
+typedef SkTRegistry<SkImageDecoder*(*)(SkStreamRewindable*)>        SkImageDecoder_DecodeReg;
+typedef SkTRegistry<SkImageDecoder::Format(*)(SkStreamRewindable*)> SkImageDecoder_FormatReg;
 
 #endif
diff --git a/include/images/SkImageRef.h b/include/images/SkImageRef.h
index bca4305..0599a8d 100644
--- a/include/images/SkImageRef.h
+++ b/include/images/SkImageRef.h
@@ -16,7 +16,7 @@
 #include "SkString.h"
 
 class SkImageRefPool;
-class SkStream;
+class SkStreamRewindable;
 
 // define this to enable dumping whenever we add/remove/purge an imageref
 //#define DUMP_IMAGEREF_LIFECYCLE
@@ -34,7 +34,8 @@
         @param config The preferred config of the decoded bitmap.
         @param sampleSize Requested sampleSize for decoding. Defaults to 1.
     */
-    SkImageRef(SkStream*, SkBitmap::Config config, int sampleSize = 1, SkBaseMutex* mutex = NULL);
+    SkImageRef(SkStreamRewindable*, SkBitmap::Config config, int sampleSize = 1,
+               SkBaseMutex* mutex = NULL);
     virtual ~SkImageRef();
 
     /** this value is passed onto the decoder. Default is true
@@ -64,7 +65,7 @@
     /** Override if you want to install a custom allocator.
         When this is called we will have already acquired the mutex!
     */
-    virtual bool onDecode(SkImageDecoder* codec, SkStream*, SkBitmap*,
+    virtual bool onDecode(SkImageDecoder* codec, SkStreamRewindable*, SkBitmap*,
                           SkBitmap::Config, SkImageDecoder::Mode);
 
     /*  Overrides from SkPixelRef
@@ -81,13 +82,13 @@
     SkBitmap fBitmap;
 
 private:
-    SkStream* setStream(SkStream*);
+    SkStreamRewindable* setStream(SkStreamRewindable*);
     // called with mutex already held. returns true if the bitmap is in the
     // requested state (or further, i.e. has pixels)
     bool prepareBitmap(SkImageDecoder::Mode);
 
     SkImageDecoderFactory*  fFactory;    // may be null
-    SkStream*               fStream;
+    SkStreamRewindable*     fStream;
     SkBitmap::Config        fConfig;
     int                     fSampleSize;
     bool                    fDoDither;
diff --git a/include/images/SkImageRef_GlobalPool.h b/include/images/SkImageRef_GlobalPool.h
index 914b0eb..3adc0f6 100644
--- a/include/images/SkImageRef_GlobalPool.h
+++ b/include/images/SkImageRef_GlobalPool.h
@@ -15,7 +15,8 @@
 class SkImageRef_GlobalPool : public SkImageRef {
 public:
     // if pool is null, use the global pool
-    SkImageRef_GlobalPool(SkStream*, SkBitmap::Config, int sampleSize = 1);
+    SkImageRef_GlobalPool(SkStreamRewindable*, SkBitmap::Config,
+                          int sampleSize = 1);
     virtual ~SkImageRef_GlobalPool();
 
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkImageRef_GlobalPool)
@@ -46,7 +47,7 @@
     static void DumpPool();
 
 protected:
-    virtual bool onDecode(SkImageDecoder* codec, SkStream* stream,
+    virtual bool onDecode(SkImageDecoder* codec, SkStreamRewindable* stream,
                           SkBitmap* bitmap, SkBitmap::Config config,
                           SkImageDecoder::Mode mode);
 
diff --git a/include/images/SkMovie.h b/include/images/SkMovie.h
index f32d609..e52a3a8 100644
--- a/include/images/SkMovie.h
+++ b/include/images/SkMovie.h
@@ -13,7 +13,7 @@
 #include "SkRefCnt.h"
 #include "SkCanvas.h"
 
-class SkStream;
+class SkStreamRewindable;
 
 class SkMovie : public SkRefCnt {
 public:
@@ -22,7 +22,7 @@
     /** Try to create a movie from the stream. If the stream format is not
         supported, return NULL.
     */
-    static SkMovie* DecodeStream(SkStream*);
+    static SkMovie* DecodeStream(SkStreamRewindable*);
     /** Try to create a movie from the specified file path. If the file is not
         found, or the format is not supported, return NULL. If a movie is
         returned, the stream may be retained by the movie (via ref()) until
diff --git a/samplecode/SamplePicture.cpp b/samplecode/SamplePicture.cpp
index 825e561..7ae8757 100644
--- a/samplecode/SamplePicture.cpp
+++ b/samplecode/SamplePicture.cpp
@@ -34,7 +34,7 @@
 
 static SkBitmap load_bitmap() {
     SkBitmap bm;
-    SkStream* stream = SkStream::NewFromFile("/skimages/sesame_street_ensemble-hp.jpg");
+    SkStreamAsset* stream = SkStream::NewFromFile("/skimages/sesame_street_ensemble-hp.jpg");
     if (stream) {
         SkAutoUnref aur(stream);
 
diff --git a/src/animator/SkDrawBitmap.cpp b/src/animator/SkDrawBitmap.cpp
index 9f657ab..568401d 100644
--- a/src/animator/SkDrawBitmap.cpp
+++ b/src/animator/SkDrawBitmap.cpp
@@ -189,7 +189,7 @@
         fBitmap.reset();
 
         //SkStream* stream = SkStream::GetURIStream(fUriBase, src.c_str());
-        SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(src.c_str()));
+        SkAutoTUnref<SkStreamAsset> stream(SkStream::NewFromFile(src.c_str()));
         if (stream.get()) {
             SkImageDecoder::DecodeStream(stream, &fBitmap);
         }
diff --git a/src/images/SkImageDecoder.cpp b/src/images/SkImageDecoder.cpp
index 7c4c477..1544edf 100644
--- a/src/images/SkImageDecoder.cpp
+++ b/src/images/SkImageDecoder.cpp
@@ -213,8 +213,8 @@
     return this->onDecodeSubset(bm, rect);
 }
 
-bool SkImageDecoder::buildTileIndex(SkStream* stream,
-                                int *width, int *height) {
+bool SkImageDecoder::buildTileIndex(SkStreamRewindable* stream,
+                                    int *width, int *height) {
     // we reset this to false before calling onBuildTileIndex
     fShouldCancelDecode = false;
 
@@ -276,7 +276,7 @@
     SkASSERT(file);
     SkASSERT(bm);
 
-    SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(file));
+    SkAutoTUnref<SkStreamRewindable> stream(SkStream::NewFromFile(file));
     if (stream.get()) {
         if (SkImageDecoder::DecodeStream(stream, bm, pref, mode, format)) {
             bm->pixelRef()->setURI(file);
@@ -445,8 +445,9 @@
 }
 
 
-bool SkImageDecoder::DecodeStream(SkStream* stream, SkBitmap* bm,
-                          SkBitmap::Config pref, Mode mode, Format* format) {
+bool SkImageDecoder::DecodeStream(SkStreamRewindable* stream, SkBitmap* bm,
+                                  SkBitmap::Config pref, Mode mode,
+                                  Format* format) {
     SkASSERT(stream);
     SkASSERT(bm);
 
diff --git a/src/images/SkImageDecoder_FactoryDefault.cpp b/src/images/SkImageDecoder_FactoryDefault.cpp
index 247f571..e959c8b 100644
--- a/src/images/SkImageDecoder_FactoryDefault.cpp
+++ b/src/images/SkImageDecoder_FactoryDefault.cpp
@@ -10,17 +10,17 @@
 #include "SkMovie.h"
 #include "SkStream.h"
 
-extern SkImageDecoder* image_decoder_from_stream(SkStream*);
+extern SkImageDecoder* image_decoder_from_stream(SkStreamRewindable*);
 
-SkImageDecoder* SkImageDecoder::Factory(SkStream* stream) {
+SkImageDecoder* SkImageDecoder::Factory(SkStreamRewindable* stream) {
     return image_decoder_from_stream(stream);
 }
 
 /////////////////////////////////////////////////////////////////////////
 
-typedef SkTRegistry<SkMovie*(*)(SkStream*)> MovieReg;
+typedef SkTRegistry<SkMovie*(*)(SkStreamRewindable*)> MovieReg;
 
-SkMovie* SkMovie::DecodeStream(SkStream* stream) {
+SkMovie* SkMovie::DecodeStream(SkStreamRewindable* stream) {
     const MovieReg* curr = MovieReg::Head();
     while (curr) {
         SkMovie* movie = curr->factory()(stream);
diff --git a/src/images/SkImageDecoder_FactoryRegistrar.cpp b/src/images/SkImageDecoder_FactoryRegistrar.cpp
index 9ed17e0..b47a6d5 100644
--- a/src/images/SkImageDecoder_FactoryRegistrar.cpp
+++ b/src/images/SkImageDecoder_FactoryRegistrar.cpp
@@ -12,13 +12,13 @@
 
 // This file is used for registration of SkImageDecoders. It also holds a function
 // for checking all the the registered SkImageDecoders for one that matches an
-// input SkStream.
+// input SkStreamRewindable.
 
 template SkImageDecoder_DecodeReg* SkImageDecoder_DecodeReg::gHead;
 
-SkImageDecoder* image_decoder_from_stream(SkStream*);
+SkImageDecoder* image_decoder_from_stream(SkStreamRewindable*);
 
-SkImageDecoder* image_decoder_from_stream(SkStream* stream) {
+SkImageDecoder* image_decoder_from_stream(SkStreamRewindable* stream) {
     SkImageDecoder* codec = NULL;
     const SkImageDecoder_DecodeReg* curr = SkImageDecoder_DecodeReg::Head();
     while (curr) {
@@ -45,7 +45,7 @@
 
 template SkImageDecoder_FormatReg* SkImageDecoder_FormatReg::gHead;
 
-SkImageDecoder::Format SkImageDecoder::GetStreamFormat(SkStream* stream) {
+SkImageDecoder::Format SkImageDecoder::GetStreamFormat(SkStreamRewindable* stream) {
     const SkImageDecoder_FormatReg* curr = SkImageDecoder_FormatReg::Head();
     while (curr != NULL) {
         Format format = curr->factory()(stream);
diff --git a/src/images/SkImageDecoder_libbmp.cpp b/src/images/SkImageDecoder_libbmp.cpp
index 2edd57c..3eb181f 100644
--- a/src/images/SkImageDecoder_libbmp.cpp
+++ b/src/images/SkImageDecoder_libbmp.cpp
@@ -34,7 +34,7 @@
 DEFINE_DECODER_CREATOR(BMPImageDecoder);
 ///////////////////////////////////////////////////////////////////////////////
 
-static bool is_bmp(SkStream* stream) {
+static bool is_bmp(SkStreamRewindable* stream) {
     static const char kBmpMagic[] = { 'B', 'M' };
 
 
@@ -44,7 +44,7 @@
         !memcmp(buffer, kBmpMagic, sizeof(kBmpMagic));
 }
 
-static SkImageDecoder* sk_libbmp_dfactory(SkStream* stream) {
+static SkImageDecoder* sk_libbmp_dfactory(SkStreamRewindable* stream) {
     if (is_bmp(stream)) {
         return SkNEW(SkBMPImageDecoder);
     }
@@ -53,7 +53,7 @@
 
 static SkImageDecoder_DecodeReg gReg(sk_libbmp_dfactory);
 
-static SkImageDecoder::Format get_format_bmp(SkStream* stream) {
+static SkImageDecoder::Format get_format_bmp(SkStreamRewindable* stream) {
     if (is_bmp(stream)) {
         return SkImageDecoder::kBMP_Format;
     }
diff --git a/src/images/SkImageDecoder_libgif.cpp b/src/images/SkImageDecoder_libgif.cpp
index 21d95aa..1d25120 100644
--- a/src/images/SkImageDecoder_libgif.cpp
+++ b/src/images/SkImageDecoder_libgif.cpp
@@ -356,7 +356,7 @@
 DEFINE_DECODER_CREATOR(GIFImageDecoder);
 ///////////////////////////////////////////////////////////////////////////////
 
-static bool is_gif(SkStream* stream) {
+static bool is_gif(SkStreamRewindable* stream) {
     char buf[GIF_STAMP_LEN];
     if (stream->read(buf, GIF_STAMP_LEN) == GIF_STAMP_LEN) {
         if (memcmp(GIF_STAMP,   buf, GIF_STAMP_LEN) == 0 ||
@@ -368,7 +368,7 @@
     return false;
 }
 
-static SkImageDecoder* sk_libgif_dfactory(SkStream* stream) {
+static SkImageDecoder* sk_libgif_dfactory(SkStreamRewindable* stream) {
     if (is_gif(stream)) {
         return SkNEW(SkGIFImageDecoder);
     }
@@ -377,7 +377,7 @@
 
 static SkImageDecoder_DecodeReg gReg(sk_libgif_dfactory);
 
-static SkImageDecoder::Format get_format_gif(SkStream* stream) {
+static SkImageDecoder::Format get_format_gif(SkStreamRewindable* stream) {
     if (is_gif(stream)) {
         return SkImageDecoder::kGIF_Format;
     }
diff --git a/src/images/SkImageDecoder_libico.cpp b/src/images/SkImageDecoder_libico.cpp
index c0f0f91..2b65a36 100644
--- a/src/images/SkImageDecoder_libico.cpp
+++ b/src/images/SkImageDecoder_libico.cpp
@@ -383,7 +383,7 @@
 DEFINE_DECODER_CREATOR(ICOImageDecoder);
 /////////////////////////////////////////////////////////////////////////////////////////
 
-static bool is_ico(SkStream* stream) {
+static bool is_ico(SkStreamRewindable* stream) {
     // Check to see if the first four bytes are 0,0,1,0
     // FIXME: Is that required and sufficient?
     SkAutoMalloc autoMal(4);
@@ -398,7 +398,7 @@
     return true;
 }
 
-static SkImageDecoder* sk_libico_dfactory(SkStream* stream) {
+static SkImageDecoder* sk_libico_dfactory(SkStreamRewindable* stream) {
     if (is_ico(stream)) {
         return SkNEW(SkICOImageDecoder);
     }
@@ -407,7 +407,7 @@
 
 static SkImageDecoder_DecodeReg gReg(sk_libico_dfactory);
 
-static SkImageDecoder::Format get_format_ico(SkStream* stream) {
+static SkImageDecoder::Format get_format_ico(SkStreamRewindable* stream) {
     if (is_ico(stream)) {
         return SkImageDecoder::kICO_Format;
     }
diff --git a/src/images/SkImageDecoder_libjpeg.cpp b/src/images/SkImageDecoder_libjpeg.cpp
index 107441b..37be2a7 100644
--- a/src/images/SkImageDecoder_libjpeg.cpp
+++ b/src/images/SkImageDecoder_libjpeg.cpp
@@ -65,7 +65,7 @@
 #ifdef SK_BUILD_FOR_ANDROID
 class SkJPEGImageIndex {
 public:
-    SkJPEGImageIndex(SkStream* stream, SkImageDecoder* decoder)
+    SkJPEGImageIndex(SkStreamRewindable* stream, SkImageDecoder* decoder)
         : fSrcMgr(stream, decoder)
         , fInfoInitialized(false)
         , fHuffmanCreated(false)
@@ -195,7 +195,7 @@
 
 protected:
 #ifdef SK_BUILD_FOR_ANDROID
-    virtual bool onBuildTileIndex(SkStream *stream, int *width, int *height) SK_OVERRIDE;
+    virtual bool onBuildTileIndex(SkStreamRewindable *stream, int *width, int *height) SK_OVERRIDE;
     virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& rect) SK_OVERRIDE;
 #endif
     virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE;
@@ -638,7 +638,7 @@
 }
 
 #ifdef SK_BUILD_FOR_ANDROID
-bool SkJPEGImageDecoder::onBuildTileIndex(SkStream* stream, int *width, int *height) {
+bool SkJPEGImageDecoder::onBuildTileIndex(SkStreamRewindable* stream, int *width, int *height) {
 
     SkAutoTDelete<SkJPEGImageIndex> imageIndex(SkNEW_ARGS(SkJPEGImageIndex, (stream, this)));
     jpeg_decompress_struct* cinfo = imageIndex->cinfo();
@@ -1121,7 +1121,7 @@
 DEFINE_ENCODER_CREATOR(JPEGImageEncoder);
 ///////////////////////////////////////////////////////////////////////////////
 
-static bool is_jpeg(SkStream* stream) {
+static bool is_jpeg(SkStreamRewindable* stream) {
     static const unsigned char gHeader[] = { 0xFF, 0xD8, 0xFF };
     static const size_t HEADER_SIZE = sizeof(gHeader);
 
@@ -1137,14 +1137,15 @@
     return true;
 }
 
-static SkImageDecoder* sk_libjpeg_dfactory(SkStream* stream) {
+
+static SkImageDecoder* sk_libjpeg_dfactory(SkStreamRewindable* stream) {
     if (is_jpeg(stream)) {
         return SkNEW(SkJPEGImageDecoder);
     }
     return NULL;
 }
 
-static SkImageDecoder::Format get_format_jpeg(SkStream* stream) {
+static SkImageDecoder::Format get_format_jpeg(SkStreamRewindable* stream) {
     if (is_jpeg(stream)) {
         return SkImageDecoder::kJPEG_Format;
     }
@@ -1155,7 +1156,6 @@
     return (SkImageEncoder::kJPEG_Type == t) ? SkNEW(SkJPEGImageEncoder) : NULL;
 }
 
-
 static SkImageDecoder_DecodeReg gDReg(sk_libjpeg_dfactory);
 static SkImageDecoder_FormatReg gFormatReg(get_format_jpeg);
 static SkImageEncoder_EncodeReg gEReg(sk_libjpeg_efactory);
diff --git a/src/images/SkImageDecoder_libpng.cpp b/src/images/SkImageDecoder_libpng.cpp
index 56c19fd..b6aa329 100644
--- a/src/images/SkImageDecoder_libpng.cpp
+++ b/src/images/SkImageDecoder_libpng.cpp
@@ -42,7 +42,7 @@
 
 class SkPNGImageIndex {
 public:
-    SkPNGImageIndex(SkStream* stream, png_structp png_ptr, png_infop info_ptr)
+    SkPNGImageIndex(SkStreamRewindable* stream, png_structp png_ptr, png_infop info_ptr)
         : fStream(stream)
         , fPng_ptr(png_ptr)
         , fInfo_ptr(info_ptr)
@@ -56,10 +56,10 @@
         }
     }
 
-    SkAutoTUnref<SkStream>  fStream;
-    png_structp             fPng_ptr;
-    png_infop               fInfo_ptr;
-    SkBitmap::Config        fConfig;
+    SkAutoTUnref<SkStreamRewindable>    fStream;
+    png_structp                         fPng_ptr;
+    png_infop                           fInfo_ptr;
+    SkBitmap::Config                    fConfig;
 };
 
 class SkPNGImageDecoder : public SkImageDecoder {
@@ -77,7 +77,7 @@
 
 protected:
 #ifdef SK_BUILD_FOR_ANDROID
-    virtual bool onBuildTileIndex(SkStream *stream, int *width, int *height) SK_OVERRIDE;
+    virtual bool onBuildTileIndex(SkStreamRewindable *stream, int *width, int *height) SK_OVERRIDE;
     virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& region) SK_OVERRIDE;
 #endif
     virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE;
@@ -123,7 +123,7 @@
 
 #ifdef SK_BUILD_FOR_ANDROID
 static void sk_seek_fn(png_structp png_ptr, png_uint_32 offset) {
-    SkStream* sk_stream = (SkStream*) png_get_io_ptr(png_ptr);
+    SkStreamRewindable* sk_stream = (SkStreamRewindable*) png_get_io_ptr(png_ptr);
     if (!sk_stream->rewind()) {
         png_error(png_ptr, "Failed to rewind stream!");
     }
@@ -667,7 +667,7 @@
 
 #ifdef SK_BUILD_FOR_ANDROID
 
-bool SkPNGImageDecoder::onBuildTileIndex(SkStream* sk_stream, int *width, int *height) {
+bool SkPNGImageDecoder::onBuildTileIndex(SkStreamRewindable* sk_stream, int *width, int *height) {
     png_structp png_ptr;
     png_infop   info_ptr;
 
@@ -1174,7 +1174,7 @@
 DEFINE_ENCODER_CREATOR(PNGImageEncoder);
 ///////////////////////////////////////////////////////////////////////////////
 
-static bool is_png(SkStream* stream) {
+static bool is_png(SkStreamRewindable* stream) {
     char buf[PNG_BYTES_TO_CHECK];
     if (stream->read(buf, PNG_BYTES_TO_CHECK) == PNG_BYTES_TO_CHECK &&
         !png_sig_cmp((png_bytep) buf, (png_size_t)0, PNG_BYTES_TO_CHECK)) {
@@ -1183,14 +1183,14 @@
     return false;
 }
 
-SkImageDecoder* sk_libpng_dfactory(SkStream* stream) {
+SkImageDecoder* sk_libpng_dfactory(SkStreamRewindable* stream) {
     if (is_png(stream)) {
         return SkNEW(SkPNGImageDecoder);
     }
     return NULL;
 }
 
-static SkImageDecoder::Format get_format_png(SkStream* stream) {
+static SkImageDecoder::Format get_format_png(SkStreamRewindable* stream) {
     if (is_png(stream)) {
         return SkImageDecoder::kPNG_Format;
     }
diff --git a/src/images/SkImageDecoder_libwebp.cpp b/src/images/SkImageDecoder_libwebp.cpp
index a6a6991..625e96e 100644
--- a/src/images/SkImageDecoder_libwebp.cpp
+++ b/src/images/SkImageDecoder_libwebp.cpp
@@ -110,7 +110,7 @@
     }
 
 protected:
-    virtual bool onBuildTileIndex(SkStream *stream, int *width, int *height) SK_OVERRIDE;
+    virtual bool onBuildTileIndex(SkStreamRewindable *stream, int *width, int *height) SK_OVERRIDE;
     virtual bool onDecodeSubset(SkBitmap* bitmap, const SkIRect& rect) SK_OVERRIDE;
     virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE;
 
@@ -300,7 +300,7 @@
     return true;
 }
 
-bool SkWEBPImageDecoder::onBuildTileIndex(SkStream* stream,
+bool SkWEBPImageDecoder::onBuildTileIndex(SkStreamRewindable* stream,
                                           int *width, int *height) {
     int origWidth, origHeight, hasAlpha;
     if (!webp_parse_header(stream, &origWidth, &origHeight, &hasAlpha)) {
@@ -575,7 +575,7 @@
 DEFINE_ENCODER_CREATOR(WEBPImageEncoder);
 ///////////////////////////////////////////////////////////////////////////////
 
-static SkImageDecoder* sk_libwebp_dfactory(SkStream* stream) {
+static SkImageDecoder* sk_libwebp_dfactory(SkStreamRewindable* stream) {
     int width, height, hasAlpha;
     if (!webp_parse_header(stream, &width, &height, &hasAlpha)) {
         return NULL;
@@ -585,7 +585,7 @@
     return SkNEW(SkWEBPImageDecoder);
 }
 
-static SkImageDecoder::Format get_format_webp(SkStream* stream) {
+static SkImageDecoder::Format get_format_webp(SkStreamRewindable* stream) {
     int width, height, hasAlpha;
     if (webp_parse_header(stream, &width, &height, &hasAlpha)) {
         return SkImageDecoder::kWEBP_Format;
diff --git a/src/images/SkImageDecoder_wbmp.cpp b/src/images/SkImageDecoder_wbmp.cpp
index 9460d55..4a9944d 100644
--- a/src/images/SkImageDecoder_wbmp.cpp
+++ b/src/images/SkImageDecoder_wbmp.cpp
@@ -152,7 +152,7 @@
 DEFINE_DECODER_CREATOR(WBMPImageDecoder);
 ///////////////////////////////////////////////////////////////////////////////
 
-static SkImageDecoder* sk_wbmp_dfactory(SkStream* stream) {
+static SkImageDecoder* sk_wbmp_dfactory(SkStreamRewindable* stream) {
     wbmp_head   head;
 
     if (head.init(stream)) {
@@ -161,7 +161,7 @@
     return NULL;
 }
 
-static SkImageDecoder::Format get_format_wbmp(SkStream* stream) {
+static SkImageDecoder::Format get_format_wbmp(SkStreamRewindable* stream) {
     wbmp_head head;
     if (head.init(stream)) {
         return SkImageDecoder::kWBMP_Format;
diff --git a/src/images/SkImageRef.cpp b/src/images/SkImageRef.cpp
index bd4a739..9093b05 100644
--- a/src/images/SkImageRef.cpp
+++ b/src/images/SkImageRef.cpp
@@ -18,7 +18,7 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-SkImageRef::SkImageRef(SkStream* stream, SkBitmap::Config config,
+SkImageRef::SkImageRef(SkStreamRewindable* stream, SkBitmap::Config config,
                        int sampleSize, SkBaseMutex* mutex)
         : SkPixelRef(mutex), fErrorInDecoding(false) {
     SkASSERT(stream);
@@ -79,7 +79,7 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-bool SkImageRef::onDecode(SkImageDecoder* codec, SkStream* stream,
+bool SkImageRef::onDecode(SkImageDecoder* codec, SkStreamRewindable* stream,
                           SkBitmap* bitmap, SkBitmap::Config config,
                           SkImageDecoder::Mode mode) {
     return codec->decode(stream, bitmap, config, mode);
diff --git a/src/images/SkImageRef_GlobalPool.cpp b/src/images/SkImageRef_GlobalPool.cpp
index 6af8653..352dd42 100644
--- a/src/images/SkImageRef_GlobalPool.cpp
+++ b/src/images/SkImageRef_GlobalPool.cpp
@@ -24,7 +24,7 @@
     return gPool;
 }
 
-SkImageRef_GlobalPool::SkImageRef_GlobalPool(SkStream* stream,
+SkImageRef_GlobalPool::SkImageRef_GlobalPool(SkStreamRewindable* stream,
                                              SkBitmap::Config config,
                                              int sampleSize)
         : SkImageRef(stream, config, sampleSize, &gGlobalPoolMutex) {
@@ -44,7 +44,7 @@
  *  that we also are already inside the mutex. Hence, we can reference
  *  the global-pool directly.
  */
-bool SkImageRef_GlobalPool::onDecode(SkImageDecoder* codec, SkStream* stream,
+bool SkImageRef_GlobalPool::onDecode(SkImageDecoder* codec, SkStreamRewindable* stream,
                                      SkBitmap* bitmap, SkBitmap::Config config,
                                      SkImageDecoder::Mode mode) {
     if (!this->INHERITED::onDecode(codec, stream, bitmap, config, mode)) {
diff --git a/src/images/SkImageRef_ashmem.cpp b/src/images/SkImageRef_ashmem.cpp
index a4058ff..0186bf6 100644
--- a/src/images/SkImageRef_ashmem.cpp
+++ b/src/images/SkImageRef_ashmem.cpp
@@ -31,7 +31,7 @@
     return newsize;
 }
 
-SkImageRef_ashmem::SkImageRef_ashmem(SkStream* stream,
+SkImageRef_ashmem::SkImageRef_ashmem(SkStreamRewindable* stream,
                                              SkBitmap::Config config,
                                              int sampleSize)
         : SkImageRef(stream, config, sampleSize) {
@@ -126,7 +126,7 @@
     const char*  fName;
 };
 
-bool SkImageRef_ashmem::onDecode(SkImageDecoder* codec, SkStream* stream,
+bool SkImageRef_ashmem::onDecode(SkImageDecoder* codec, SkStreamRewindable* stream,
                                  SkBitmap* bitmap, SkBitmap::Config config,
                                  SkImageDecoder::Mode mode) {
 
diff --git a/src/images/SkImageRef_ashmem.h b/src/images/SkImageRef_ashmem.h
index f98507a..efee5e7 100644
--- a/src/images/SkImageRef_ashmem.h
+++ b/src/images/SkImageRef_ashmem.h
@@ -19,7 +19,7 @@
 
 class SkImageRef_ashmem : public SkImageRef {
 public:
-    SkImageRef_ashmem(SkStream*, SkBitmap::Config, int sampleSize = 1);
+    SkImageRef_ashmem(SkStreamRewindable*, SkBitmap::Config, int sampleSize = 1);
     virtual ~SkImageRef_ashmem();
 
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkImageRef_ashmem)
@@ -28,7 +28,7 @@
     SkImageRef_ashmem(SkFlattenableReadBuffer&);
     virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
 
-    virtual bool onDecode(SkImageDecoder* codec, SkStream* stream,
+    virtual bool onDecode(SkImageDecoder* codec, SkStreamRewindable* stream,
                           SkBitmap* bitmap, SkBitmap::Config config,
                           SkImageDecoder::Mode mode);
 
diff --git a/src/images/SkMovie.cpp b/src/images/SkMovie.cpp
index 2560014..d2439eb 100644
--- a/src/images/SkMovie.cpp
+++ b/src/images/SkMovie.cpp
@@ -92,6 +92,6 @@
 }
 
 SkMovie* SkMovie::DecodeFile(const char path[]) {
-    SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
+    SkAutoTUnref<SkStreamRewindable> stream(SkStream::NewFromFile(path));
     return stream.get() ? SkMovie::DecodeStream(stream) : NULL;
 }
diff --git a/src/images/SkMovie_gif.cpp b/src/images/SkMovie_gif.cpp
index e4c7003..b6d068a 100644
--- a/src/images/SkMovie_gif.cpp
+++ b/src/images/SkMovie_gif.cpp
@@ -432,7 +432,7 @@
 
 #include "SkTRegistry.h"
 
-SkMovie* Factory(SkStream* stream) {
+SkMovie* Factory(SkStreamRewindable* stream) {
     char buf[GIF_STAMP_LEN];
     if (stream->read(buf, GIF_STAMP_LEN) == GIF_STAMP_LEN) {
         if (memcmp(GIF_STAMP,   buf, GIF_STAMP_LEN) == 0 ||
@@ -446,4 +446,4 @@
     return NULL;
 }
 
-static SkTRegistry<SkMovie*(*)(SkStream*)> gReg(Factory);
+static SkTRegistry<SkMovie*(*)(SkStreamRewindable*)> gReg(Factory);
diff --git a/src/ports/SkImageDecoder_CG.cpp b/src/ports/SkImageDecoder_CG.cpp
index 9751f72..8956aca 100644
--- a/src/ports/SkImageDecoder_CG.cpp
+++ b/src/ports/SkImageDecoder_CG.cpp
@@ -126,9 +126,9 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-extern SkImageDecoder* image_decoder_from_stream(SkStream*);
+extern SkImageDecoder* image_decoder_from_stream(SkStreamRewindable*);
 
-SkImageDecoder* SkImageDecoder::Factory(SkStream* stream) {
+SkImageDecoder* SkImageDecoder::Factory(SkStreamRewindable* stream) {
     SkImageDecoder* decoder = image_decoder_from_stream(stream);
     if (NULL == decoder) {
         // If no image decoder specific to the stream exists, use SkImageDecoder_CG.
@@ -140,7 +140,7 @@
 
 /////////////////////////////////////////////////////////////////////////
 
-SkMovie* SkMovie::DecodeStream(SkStream* stream) {
+SkMovie* SkMovie::DecodeStream(SkStreamRewindable* stream) {
     return NULL;
 }
 
@@ -244,8 +244,6 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-#include "SkTRegistry.h"
-
 static SkImageEncoder* sk_imageencoder_cg_factory(SkImageEncoder::Type t) {
     switch (t) {
         case SkImageEncoder::kICO_Type:
@@ -260,7 +258,7 @@
     return SkNEW_ARGS(SkImageEncoder_CG, (t));
 }
 
-static SkTRegistry<SkImageEncoder*(*)(SkImageEncoder::Type)> gEReg(sk_imageencoder_cg_factory);
+static SkImageEncoder_EncodeReg gEReg(sk_imageencoder_cg_factory);
 
 struct FormatConversion {
     CFStringRef             fUTType;
@@ -287,7 +285,7 @@
     return SkImageDecoder::kUnknown_Format;
 }
 
-static SkImageDecoder::Format get_format_cg(SkStream *stream) {
+static SkImageDecoder::Format get_format_cg(SkStreamRewindable* stream) {
     CGImageSourceRef imageSrc = SkStreamToCGImageSource(stream);
 
     if (NULL == imageSrc) {
@@ -302,4 +300,4 @@
     return UTType_to_Format(name);
 }
 
-static SkTRegistry<SkImageDecoder::Format(*)(SkStream*)> gFormatReg(get_format_cg);
+static SkImageDecoder_FormatReg gFormatReg(get_format_cg);
diff --git a/src/ports/SkImageDecoder_WIC.cpp b/src/ports/SkImageDecoder_WIC.cpp
index 54d0427..7b2ae9e 100644
--- a/src/ports/SkImageDecoder_WIC.cpp
+++ b/src/ports/SkImageDecoder_WIC.cpp
@@ -230,9 +230,9 @@
 
 /////////////////////////////////////////////////////////////////////////
 
-extern SkImageDecoder* image_decoder_from_stream(SkStream*);
+extern SkImageDecoder* image_decoder_from_stream(SkStreamRewindable*);
 
-SkImageDecoder* SkImageDecoder::Factory(SkStream* stream) {
+SkImageDecoder* SkImageDecoder::Factory(SkStreamRewindable* stream) {
     SkImageDecoder* decoder = image_decoder_from_stream(stream);
     if (NULL == decoder) {
         // If no image decoder specific to the stream exists, use SkImageDecoder_WIC.
@@ -244,7 +244,7 @@
 
 /////////////////////////////////////////////////////////////////////////
 
-SkMovie* SkMovie::DecodeStream(SkStream* stream) {
+SkMovie* SkMovie::DecodeStream(SkStreamRewindable* stream) {
     return NULL;
 }
 
@@ -417,8 +417,6 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-#include "SkTRegistry.h"
-
 static SkImageEncoder* sk_imageencoder_wic_factory(SkImageEncoder::Type t) {
     switch (t) {
         case SkImageEncoder::kBMP_Type:
@@ -432,9 +430,9 @@
     return SkNEW_ARGS(SkImageEncoder_WIC, (t));
 }
 
-static SkTRegistry<SkImageEncoder*(*)(SkImageEncoder::Type)> gEReg(sk_imageencoder_wic_factory);
+static SkImageEncoder_EncodeReg gEReg(sk_imageencoder_wic_factory);
 
-static SkImageDecoder::Format get_format_wic(SkStream* stream) {
+static SkImageDecoder::Format get_format_wic(SkStreamRewindable* stream) {
     SkImageDecoder::Format format;
     SkImageDecoder_WIC codec;
     if (!codec.decodeStream(stream, NULL, SkImageDecoder_WIC::kDecodeFormat_WICMode, &format)) {
@@ -443,4 +441,4 @@
     return format;
 }
 
-static SkTRegistry<SkImageDecoder::Format(*)(SkStream*)> gFormatReg(get_format_wic);
+static SkImageDecoder_FormatReg gFormatReg(get_format_wic);
diff --git a/src/ports/SkImageDecoder_empty.cpp b/src/ports/SkImageDecoder_empty.cpp
index c225bb1..69e6ec9 100644
--- a/src/ports/SkImageDecoder_empty.cpp
+++ b/src/ports/SkImageDecoder_empty.cpp
@@ -15,10 +15,11 @@
 
 class SkColorTable;
 class SkStream;
+class SkStreamRewindable;
 
 // Empty implementations for SkImageDecoder.
 
-SkImageDecoder* SkImageDecoder::Factory(SkStream*) {
+SkImageDecoder* SkImageDecoder::Factory(SkStreamRewindable*) {
     return NULL;
 }
 
@@ -33,7 +34,7 @@
     return false;
 }
 
-bool SkImageDecoder::DecodeStream(SkStream*, SkBitmap*, SkBitmap::Config,
+bool SkImageDecoder::DecodeStream(SkStreamRewindable*, SkBitmap*, SkBitmap::Config,
                                   SkImageDecoder::Mode,
                                   SkImageDecoder::Format*) {
     return false;
@@ -45,7 +46,7 @@
     return false;
 }
 
-bool SkImageDecoder::buildTileIndex(SkStream*, int *width, int *height) {
+bool SkImageDecoder::buildTileIndex(SkStreamRewindable*, int *width, int *height) {
     return false;
 }
 
@@ -57,7 +58,7 @@
     return kUnknown_Format;
 }
 
-SkImageDecoder::Format SkImageDecoder::GetStreamFormat(SkStream*) {
+SkImageDecoder::Format SkImageDecoder::GetStreamFormat(SkStreamRewindable*) {
     return kUnknown_Format;
 }
 
@@ -112,7 +113,7 @@
 
 // Empty implementation for SkMovie.
 
-SkMovie* SkMovie::DecodeStream(SkStream* stream) {
+SkMovie* SkMovie::DecodeStream(SkStreamRewindable* stream) {
     return NULL;
 }
 
diff --git a/src/utils/win/SkIStream.cpp b/src/utils/win/SkIStream.cpp
index 7880fa0..182d9a8 100644
--- a/src/utils/win/SkIStream.cpp
+++ b/src/utils/win/SkIStream.cpp
@@ -176,6 +176,8 @@
         if (!this->fSkStream->rewind()) {
             hr = E_FAIL;
         } else {
+            // FIXME: Should not depend on getLength.
+            // See https://code.google.com/p/skia/issues/detail?id=1570
             LONGLONG skip = this->fSkStream->getLength()
                           + liDistanceToMove.QuadPart;
             size_t skipped = this->fSkStream->skip(static_cast<size_t>(skip));
@@ -204,6 +206,8 @@
         return STG_E_INVALIDFLAG;
     }
     pStatstg->pwcsName = NULL;
+    // FIXME: Should not depend on getLength
+    // See https://code.google.com/p/skia/issues/detail?id=1570
     pStatstg->cbSize.QuadPart = this->fSkStream->getLength();
     pStatstg->clsid = CLSID_NULL;
     pStatstg->type = STGTY_STREAM;
diff --git a/tests/ImageDecodingTest.cpp b/tests/ImageDecodingTest.cpp
index 5764ffb..89d18ab 100644
--- a/tests/ImageDecodingTest.cpp
+++ b/tests/ImageDecodingTest.cpp
@@ -194,7 +194,7 @@
 
 #ifdef SK_DEBUG
 // Create a stream containing a bitmap encoded to Type type.
-static SkStream* create_image_stream(SkImageEncoder::Type type) {
+static SkMemoryStream* create_image_stream(SkImageEncoder::Type type) {
     SkBitmap bm;
     const int size = 50;
     bm.setConfig(SkBitmap::kARGB_8888_Config, size, size);
@@ -233,7 +233,7 @@
     };
     for (size_t i = 0; i < SK_ARRAY_COUNT(gTypes); ++i) {
         //SkDebugf("encoding to %i\n", i);
-        SkAutoTUnref<SkStream> stream(create_image_stream(gTypes[i]));
+        SkAutoTUnref<SkMemoryStream> stream(create_image_stream(gTypes[i]));
         if (NULL == stream.get()) {
             SkDebugf("no stream\n");
             continue;