SkDecodingImageGenerator now uses SkStreamRewindable

This makes sense since Android will be giving us a stream and the
decoders expect a stream.  This also removes some glue code,
DecodeMemoryToTarget, that works better using a SkImageGenerator.

Motivation: This is a necessary step to move from SkImageRef to
SkDiscardablePixelRef.

SkImageDecoder::DecodeMemoryToTarget function removed.

BUG=
R=reed@google.com, scroggo@google.com

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

git-svn-id: http://skia.googlecode.com/svn/trunk@12560 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/images/SkDecodingImageGenerator.cpp b/src/images/SkDecodingImageGenerator.cpp
index 05651c7..2b80444 100644
--- a/src/images/SkDecodingImageGenerator.cpp
+++ b/src/images/SkDecodingImageGenerator.cpp
@@ -9,39 +9,184 @@
 #include "SkData.h"
 #include "SkDiscardablePixelRef.h"
 #include "SkImageDecoder.h"
+#include "SkImagePriv.h"
+#include "SkStream.h"
+
+
+namespace {
+/**
+ *  Special allocator used by getPixels(). Uses preallocated memory
+ *  provided.
+ */
+class TargetAllocator : public SkBitmap::Allocator {
+public:
+    TargetAllocator(void* target, size_t rowBytes, const SkImageInfo& info)
+        : fTarget(target)
+        , fRowBytes(rowBytes)
+        , fInfo(info) { }
+
+    virtual bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) SK_OVERRIDE {
+        if ((SkImageInfoToBitmapConfig(fInfo) != bm->config())
+            || (bm->width() != fInfo.fWidth)
+            || (bm->height() != fInfo.fHeight)) {
+            return false;
+        }
+        bm->setConfig(bm->config(), bm->width(), bm->height(),
+                      fRowBytes, bm->alphaType());
+        bm->setPixels(fTarget, ct);
+        return true;
+    }
+
+private:
+    void* fTarget;
+    size_t fRowBytes;
+    SkImageInfo fInfo;
+    typedef SkBitmap::Allocator INHERITED;
+};
+}  // namespace
+////////////////////////////////////////////////////////////////////////////////
 
 SkDecodingImageGenerator::SkDecodingImageGenerator(SkData* data)
-    : fData(data) {
+    : fData(data)
+    , fHasInfo(false)
+    , fDoCopyTo(false) {
     SkASSERT(fData != NULL);
+    fStream = SkNEW_ARGS(SkMemoryStream, (fData));
+    SkASSERT(fStream != NULL);
+    SkASSERT(fStream->unique());
     fData->ref();
 }
 
+SkDecodingImageGenerator::SkDecodingImageGenerator(SkStreamRewindable* stream)
+    : fData(NULL)
+    , fStream(stream)
+    , fHasInfo(false)
+    , fDoCopyTo(false) {
+    SkASSERT(fStream != NULL);
+    SkASSERT(fStream->unique());
+}
+
 SkDecodingImageGenerator::~SkDecodingImageGenerator() {
-    fData->unref();
+    SkSafeUnref(fData);
+    fStream->unref();
 }
 
+// TODO(halcanary): Give this macro a better name and move it into SkTypes.h
+#ifdef SK_DEBUG
+    #define SkCheckResult(expr, value)  SkASSERT((value) == (expr))
+#else
+    #define SkCheckResult(expr, value)  (void)(expr)
+#endif
+
 SkData* SkDecodingImageGenerator::refEncodedData() {
     // This functionality is used in `gm --serialize`
-    fData->ref();
-    return fData;
+    if (fData != NULL) {
+        return SkSafeRef(fData);
+    }
+    // TODO(halcanary): SkStreamRewindable needs a refData() function
+    // which returns a cheap copy of the underlying data.
+    if (!fStream->rewind()) {
+        return NULL;
+    }
+    size_t length = fStream->getLength();
+    if (0 == length) {
+        return NULL;
+    }
+    void* buffer = sk_malloc_flags(length, 0);
+    SkCheckResult(fStream->read(buffer, length), length);
+    fData = SkData::NewFromMalloc(buffer, length);
+    return SkSafeRef(fData);
 }
 
 bool SkDecodingImageGenerator::getInfo(SkImageInfo* info) {
-    SkASSERT(info != NULL);
-    return SkImageDecoder::DecodeMemoryToTarget(fData->data(),
-                                                fData->size(),
-                                                info, NULL);
+    // info can be NULL.  If so, will update fInfo, fDoCopyTo, and fHasInfo.
+    if (fHasInfo) {
+        if (info != NULL) {
+            *info = fInfo;
+        }
+        return true;
+    }
+    SkAssertResult(fStream->rewind());
+    SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(fStream));
+    if (NULL == decoder.get()) {
+        return false;
+    }
+    SkBitmap bitmap;
+    if (!decoder->decode(fStream, &bitmap,
+                         SkImageDecoder::kDecodeBounds_Mode)) {
+        return false;
+    }
+    if (bitmap.config() == SkBitmap::kNo_Config) {
+        return false;
+    }
+    if (!SkBitmapToImageInfo(bitmap, &fInfo)) {
+        // We can't use bitmap.config() as is.
+        // Must be kARGB_4444_Config.
+        if (!bitmap.canCopyTo(SkBitmap::kARGB_8888_Config)) {
+            // kARGB_4444_Config can copy to kARGB_8888.
+            SkDEBUGFAIL("!bitmap->canCopyTo(SkBitmap::kARGB_8888_Config)");
+            return false;
+        }
+        fDoCopyTo = true;
+        fInfo.fWidth = bitmap.width();
+        fInfo.fHeight = bitmap.height();
+        fInfo.fColorType = kPMColor_SkColorType;
+        fInfo.fAlphaType = bitmap.alphaType();
+    }
+    if (info != NULL) {
+        *info = fInfo;
+    }
+    fHasInfo = true;
+    return true;
 }
 
 bool SkDecodingImageGenerator::getPixels(const SkImageInfo& info,
                                          void* pixels,
                                          size_t rowBytes) {
-    SkASSERT(pixels != NULL);
-    SkImageDecoder::Target target = {pixels, rowBytes};
-    SkImageInfo tmpInfo = info;
-    return SkImageDecoder::DecodeMemoryToTarget(fData->data(),
-                                                fData->size(),
-                                                &tmpInfo, &target);
+    if (NULL == pixels) {
+        return false;
+    }
+    if (!this->getInfo(NULL)) {
+        return false;
+    }
+    if (SkImageInfoToBitmapConfig(info) == SkBitmap::kNo_Config) {
+        return false;  // Unsupported SkColorType.
+    }
+    SkAssertResult(fStream->rewind());
+    SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(fStream));
+    if (NULL == decoder.get()) {
+        return false;
+    }
+    if (fInfo != info) {
+        // The caller has specified a different info.  For now, this
+        // is an error.  In the future, we will check to see if we can
+        // convert.
+        return false;
+    }
+    int bpp = SkBitmap::ComputeBytesPerPixel(SkImageInfoToBitmapConfig(info));
+    if (static_cast<size_t>(bpp * info.fWidth) > rowBytes) {
+        return false;
+    }
+    SkBitmap bitmap;
+    if (!bitmap.setConfig(info, rowBytes)) {
+        return false;
+    }
+
+    TargetAllocator allocator(pixels, rowBytes, info);
+    if (!fDoCopyTo) {
+        decoder->setAllocator(&allocator);
+    }
+    bool success = decoder->decode(fStream, &bitmap,
+                                   SkImageDecoder::kDecodePixels_Mode);
+    decoder->setAllocator(NULL);
+    if (!success) {
+        return false;
+    }
+    if (fDoCopyTo) {
+        SkBitmap bm8888;
+        bitmap.copyTo(&bm8888, SkBitmap::kARGB_8888_Config, &allocator);
+    }
+    return true;
 }
 bool SkDecodingImageGenerator::Install(SkData* data, SkBitmap* dst,
                                        SkDiscardableMemory::Factory* factory) {
@@ -50,3 +195,17 @@
     SkImageGenerator* gen(SkNEW_ARGS(SkDecodingImageGenerator, (data)));
     return SkDiscardablePixelRef::Install(gen, dst, factory);
 }
+
+bool SkDecodingImageGenerator::Install(SkStreamRewindable* stream,
+                                       SkBitmap* dst,
+                                       SkDiscardableMemory::Factory* factory) {
+    SkASSERT(stream != NULL);
+    SkASSERT(dst != NULL);
+    if ((stream == NULL) || !stream->unique()) {
+        SkSafeUnref(stream);
+        return false;
+    }
+    SkImageGenerator* gen(SkNEW_ARGS(SkDecodingImageGenerator, (stream)));
+    return SkDiscardablePixelRef::Install(gen, dst, factory);
+}
+