Revert of https://codereview.chromium.org/93703004/
Reason for revert: Test failures

R=scroggo@google.com, djsollen@google.com, reed@google.com, halcanary@google.com
TBR=djsollen@google.com, halcanary@google.com, reed@google.com, scroggo@google.com
NOTREECHECKS=true
NOTRY=true

Author: robertphillips@google.com

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

git-svn-id: http://skia.googlecode.com/svn/trunk@12747 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/images/SkDecodingImageGenerator.cpp b/src/images/SkDecodingImageGenerator.cpp
index 153d1e2..a833c63 100644
--- a/src/images/SkDecodingImageGenerator.cpp
+++ b/src/images/SkDecodingImageGenerator.cpp
@@ -5,14 +5,13 @@
  * found in the LICENSE file.
  */
 
-#include "SkData.h"
 #include "SkDecodingImageGenerator.h"
+#include "SkData.h"
 #include "SkImageDecoder.h"
-#include "SkImageInfo.h"
 #include "SkImageGenerator.h"
 #include "SkImagePriv.h"
 #include "SkStream.h"
-#include "SkUtils.h"
+
 
 namespace {
 /**
@@ -21,55 +20,56 @@
  */
 class TargetAllocator : public SkBitmap::Allocator {
 public:
-    TargetAllocator(void* target,
-                    size_t rowBytes,
-                    int width,
-                    int height,
-                    SkBitmap::Config config)
+    TargetAllocator(void* target, size_t rowBytes, const SkImageInfo& info)
         : fTarget(target)
         , fRowBytes(rowBytes)
-        , fWidth(width)
-        , fHeight(height)
-        , fConfig(config) { }
+        , fInfo(info) { }
 
-    bool isReady() { return (fTarget != NULL); }
-
-    virtual bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) {
-        if ((NULL == fTarget)
-            || (fConfig != bm->config())
-            || (fWidth != bm->width())
-            || (fHeight != bm->height())
-            || (ct != NULL)) {
-            // Call default allocator.
-            return bm->allocPixels(NULL, ct);
+    virtual bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) SK_OVERRIDE {
+        if ((SkImageInfoToBitmapConfig(fInfo) != bm->config())
+            || (bm->width() != fInfo.fWidth)
+            || (bm->height() != fInfo.fHeight)) {
+            return false;
         }
-        // make sure fRowBytes is correct.
-        bm->setConfig(fConfig, fWidth, fHeight, fRowBytes, bm->alphaType());
-        // TODO(halcanary): verify that all callers of this function
-        // will respect new RowBytes.  Will be moot once rowbytes belongs
-        // to PixelRef.
-        bm->setPixels(fTarget, NULL);
-        fTarget = NULL;  // never alloc same pixels twice!
+        bm->setConfig(bm->config(), bm->width(), bm->height(),
+                      fRowBytes, bm->alphaType());
+        bm->setPixels(fTarget, ct);
         return true;
     }
 
 private:
-    void* fTarget;  // Block of memory to be supplied as pixel memory
-                    // in allocPixelRef.  Must be large enough to hold
-                    // a bitmap described by fWidth, fHeight, and
-                    // fRowBytes.
-    size_t fRowBytes;  // rowbytes for the destination bitmap
-    int fWidth;   // Along with fHeight and fConfig, the information
-    int fHeight;  // about the bitmap whose pixels this allocator is
-                  // expected to allocate. If they do not match the
-                  // bitmap passed to allocPixelRef, it is assumed
-                  // that the bitmap will be copied to a bitmap with
-                  // the correct info using this allocator, so the
-                  // default allocator will be used instead of
-                  // fTarget.
-    SkBitmap::Config fConfig;
+    void* fTarget;
+    size_t fRowBytes;
+    SkImageInfo fInfo;
     typedef SkBitmap::Allocator INHERITED;
 };
+}  // namespace
+////////////////////////////////////////////////////////////////////////////////
+
+SkDecodingImageGenerator::SkDecodingImageGenerator(SkData* 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() {
+    SkSafeUnref(fData);
+    fStream->unref();
+}
 
 // TODO(halcanary): Give this macro a better name and move it into SkTypes.h
 #ifdef SK_DEBUG
@@ -78,49 +78,8 @@
     #define SkCheckResult(expr, value)  (void)(expr)
 #endif
 
-#ifdef SK_DEBUG
-inline bool check_alpha(SkAlphaType reported, SkAlphaType actual) {
-    return ((reported == actual)
-            || ((reported == kPremul_SkAlphaType)
-                && (actual == kOpaque_SkAlphaType)));
-}
-#endif  // SK_DEBUG
-
-}  // namespace
-////////////////////////////////////////////////////////////////////////////////
-
-SkDecodingImageGenerator::SkDecodingImageGenerator(
-        SkData* data,
-        SkStreamRewindable* stream,
-        const SkImageInfo& info,
-        int sampleSize,
-        bool ditherImage,
-        SkBitmap::Config requestedConfig)
-    : fData(data)
-    , fStream(stream)
-    , fInfo(info)
-    , fSampleSize(sampleSize)
-    , fDitherImage(ditherImage)
-    , fRequestedConfig(requestedConfig) {
-    SkASSERT(stream != NULL);
-    SkSafeRef(fData);  // may be NULL.
-}
-
-SkDecodingImageGenerator::~SkDecodingImageGenerator() {
-    SkSafeUnref(fData);
-    fStream->unref();
-}
-
-bool SkDecodingImageGenerator::getInfo(SkImageInfo* info) {
-    if (info != NULL) {
-        *info = fInfo;
-    }
-    return true;
-}
-
 SkData* SkDecodingImageGenerator::refEncodedData() {
     // This functionality is used in `gm --serialize`
-    // Does not encode options.
     if (fData != NULL) {
         return SkSafeRef(fData);
     }
@@ -139,149 +98,111 @@
     return SkSafeRef(fData);
 }
 
+bool SkDecodingImageGenerator::getInfo(SkImageInfo* info) {
+    // 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 (!bitmap.asImageInfo(&fInfo)) {
+        // We can't use bitmap.config() as is.
+        if (!bitmap.canCopyTo(SkBitmap::kARGB_8888_Config)) {
+            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) {
     if (NULL == pixels) {
         return false;
     }
-    if (fInfo != info) {
-        // The caller has specified a different info.  This is an
-        // error for this kind of SkImageGenerator.  Use the Options
-        // to change the settings.
+    if (!this->getInfo(NULL)) {
         return false;
     }
-    int bpp = SkBitmap::ComputeBytesPerPixel(fRequestedConfig);
-    if (static_cast<size_t>(bpp * info.fWidth) > rowBytes) {
-        // The caller has specified a bad rowBytes.
-        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;
     }
-    decoder->setDitherImage(fDitherImage);
-    decoder->setSampleSize(fSampleSize);
-
+    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;
-    TargetAllocator allocator(pixels, rowBytes, info.fWidth,
-                              info.fHeight, fRequestedConfig);
-    decoder->setAllocator(&allocator);
-    bool success = decoder->decode(fStream, &bitmap, fRequestedConfig,
+    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 (allocator.isReady()) {  // Did not use pixels!
-        SkBitmap bm;
-        SkASSERT(bitmap.canCopyTo(fRequestedConfig));
-        if (!bitmap.copyTo(&bm, fRequestedConfig, &allocator)
-            || allocator.isReady()) {
-            SkDEBUGFAIL("bitmap.copyTo(requestedConfig) failed.");
-            // Earlier we checked canCopyto(); we expect consistency.
-            return false;
-        }
-        SkASSERT(check_alpha(fInfo.fAlphaType, bm.alphaType()));
-    } else {
-        SkASSERT(check_alpha(fInfo.fAlphaType, bitmap.alphaType()));
+    if (fDoCopyTo) {
+        SkBitmap bm8888;
+        bitmap.copyTo(&bm8888, SkBitmap::kARGB_8888_Config, &allocator);
     }
     return true;
 }
-
-SkImageGenerator* SkDecodingImageGenerator::Create(
-        SkData* data,
-        const SkDecodingImageGenerator::Options& opts) {
+bool SkDecodingImageGenerator::Install(SkData* data, SkBitmap* dst,
+                                       SkDiscardableMemory::Factory* factory) {
     SkASSERT(data != NULL);
-    if (NULL == data) {
-        return NULL;
-    }
-    SkStreamRewindable* stream = SkNEW_ARGS(SkMemoryStream, (data));
-    SkASSERT(stream != NULL);
-    SkASSERT(stream->unique());
-    return SkDecodingImageGenerator::Create(data, stream, opts);
+    SkASSERT(dst != NULL);
+    SkImageGenerator* gen(SkNEW_ARGS(SkDecodingImageGenerator, (data)));
+    return SkInstallDiscardablePixelRef(gen, dst, factory);
 }
 
-SkImageGenerator* SkDecodingImageGenerator::Create(
-        SkStreamRewindable* stream,
-        const SkDecodingImageGenerator::Options& opts) {
+bool SkDecodingImageGenerator::Install(SkStreamRewindable* stream,
+                                       SkBitmap* dst,
+                                       SkDiscardableMemory::Factory* factory) {
     SkASSERT(stream != NULL);
-    SkASSERT(stream->unique());
+    SkASSERT(dst != NULL);
     if ((stream == NULL) || !stream->unique()) {
         SkSafeUnref(stream);
-        return NULL;
+        return false;
     }
-    return SkDecodingImageGenerator::Create(NULL, stream, opts);
-}
-
-// A contructor-type function that returns NULL on failure.  This
-// prevents the returned SkImageGenerator from ever being in a bad
-// state.  Called by both Create() functions
-SkImageGenerator* SkDecodingImageGenerator::Create(
-        SkData* data,
-        SkStreamRewindable* stream,
-        const SkDecodingImageGenerator::Options& opts) {
-    SkASSERT(stream);
-    SkAutoTUnref<SkStreamRewindable> autoStream(stream);  // always unref this.
-    if (opts.fUseRequestedColorType &&
-        (kIndex_8_SkColorType == opts.fRequestedColorType)) {
-        // We do not support indexed color with SkImageGenerators,
-        return NULL;
-    }
-    SkAssertResult(autoStream->rewind());
-    SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(autoStream));
-    if (NULL == decoder.get()) {
-        return NULL;
-    }
-    SkBitmap bitmap;
-    decoder->setSampleSize(opts.fSampleSize);
-    if (!decoder->decode(stream, &bitmap,
-                         SkImageDecoder::kDecodeBounds_Mode)) {
-        return NULL;
-    }
-    if (bitmap.config() == SkBitmap::kNo_Config) {
-        return NULL;
-    }
-
-    SkImageInfo info;
-    SkBitmap::Config config;
-
-    if (!opts.fUseRequestedColorType) {
-        // Use default config.
-        if (SkBitmap::kIndex8_Config == bitmap.config()) {
-            // We don't support kIndex8 because we don't support
-            // colortables in this workflow.
-            config = SkBitmap::kARGB_8888_Config;
-            info.fWidth = bitmap.width();
-            info.fHeight = bitmap.height();
-            info.fColorType = kPMColor_SkColorType;
-            info.fAlphaType = bitmap.alphaType();
-        } else {
-            config = bitmap.config();  // Save for later!
-            if (!bitmap.asImageInfo(&info)) {
-                SkDEBUGFAIL("Getting SkImageInfo from bitmap failed.");
-                return NULL;
-            }
-        }
-    } else {
-        config = SkColorTypeToBitmapConfig(opts.fRequestedColorType);
-        if (!bitmap.canCopyTo(config)) {
-            SkASSERT(bitmap.config() != config);
-            return NULL;  // Can not translate to needed config.
-        }
-        info.fWidth = bitmap.width();
-        info.fHeight = bitmap.height();
-        info.fColorType = opts.fRequestedColorType;
-        info.fAlphaType = bitmap.alphaType();
-
-        // Sanity check.
-        SkDEBUGCODE(SkColorType tmp;)
-        SkASSERT(SkBitmapConfigToColorType(config, &tmp));
-        SkASSERT(tmp == opts.fRequestedColorType);
-    }
-    return SkNEW_ARGS(SkDecodingImageGenerator,
-                      (data, autoStream.detach(), info,
-                       opts.fSampleSize, opts.fDitherImage, config));
+    SkImageGenerator* gen(SkNEW_ARGS(SkDecodingImageGenerator, (stream)));
+    return SkInstallDiscardablePixelRef(gen, dst, factory);
 }