add new copyTo version to SkBitmap, which takes SkColorType

BUG=skia:
R=scroggo@google.com, halcanary@google.com, bsalomon@google.com

Author: reed@google.com

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

git-svn-id: http://skia.googlecode.com/svn/trunk@13553 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/images/SkDecodingImageGenerator.cpp b/src/images/SkDecodingImageGenerator.cpp
index 1e28136..7e3bb9b 100644
--- a/src/images/SkDecodingImageGenerator.cpp
+++ b/src/images/SkDecodingImageGenerator.cpp
@@ -14,60 +14,50 @@
 #include "SkStream.h"
 #include "SkUtils.h"
 
+static bool equal_modulo_alpha(const SkImageInfo& a, const SkImageInfo& b) {
+    return a.width() == b.width() && a.height() == b.height() &&
+           a.colorType() == b.colorType();
+}
+
 namespace {
 /**
  *  Special allocator used by getPixels(). Uses preallocated memory
- *  provided.
+ *  provided if possible, else fall-back on the default allocator
  */
 class TargetAllocator : public SkBitmap::Allocator {
 public:
-    TargetAllocator(void* target,
-                    size_t rowBytes,
-                    int width,
-                    int height,
-                    SkBitmap::Config config)
-        : fTarget(target)
+    TargetAllocator(const SkImageInfo& info,
+                    void* target,
+                    size_t rowBytes)
+        : fInfo(info)
+        , fTarget(target)
         , fRowBytes(rowBytes)
-        , fWidth(width)
-        , fHeight(height)
-        , fConfig(config) { }
+    {}
 
     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)) {
+        if (NULL == fTarget || !equal_modulo_alpha(fInfo, bm->info())) {
             // Call default allocator.
             return bm->allocPixels(NULL, ct);
         }
-        // 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);
+        bm->installPixels(fInfo, fTarget, fRowBytes, NULL, NULL);
+
         fTarget = NULL;  // never alloc same pixels twice!
         return true;
     }
 
 private:
+    const SkImageInfo fInfo;
     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;
+                    // a bitmap described by fInfo and fRowBytes
+    const size_t fRowBytes;  // rowbytes for the destination bitmap
+
     typedef SkBitmap::Allocator INHERITED;
 };
 
@@ -94,14 +84,13 @@
         SkStreamRewindable* stream,
         const SkImageInfo& info,
         int sampleSize,
-        bool ditherImage,
-        SkBitmap::Config requestedConfig)
+        bool ditherImage)
     : fData(data)
     , fStream(stream)
     , fInfo(info)
     , fSampleSize(sampleSize)
     , fDitherImage(ditherImage)
-    , fRequestedConfig(requestedConfig) {
+{
     SkASSERT(stream != NULL);
     SkSafeRef(fData);  // may be NULL.
 }
@@ -151,8 +140,7 @@
         // to change the settings.
         return false;
     }
-    int bpp = SkBitmap::ComputeBytesPerPixel(fRequestedConfig);
-    if (static_cast<size_t>(bpp * info.fWidth) > rowBytes) {
+    if (info.minRowBytes() > rowBytes) {
         // The caller has specified a bad rowBytes.
         return false;
     }
@@ -166,10 +154,11 @@
     decoder->setSampleSize(fSampleSize);
 
     SkBitmap bitmap;
-    TargetAllocator allocator(pixels, rowBytes, info.fWidth,
-                              info.fHeight, fRequestedConfig);
+    TargetAllocator allocator(fInfo, pixels, rowBytes);
     decoder->setAllocator(&allocator);
-    bool success = decoder->decode(fStream, &bitmap, fRequestedConfig,
+    // TODO: need to be able to pass colortype directly to decoder
+    SkBitmap::Config legacyConfig = SkColorTypeToBitmapConfig(info.colorType());
+    bool success = decoder->decode(fStream, &bitmap, legacyConfig,
                                    SkImageDecoder::kDecodePixels_Mode);
     decoder->setAllocator(NULL);
     if (!success) {
@@ -177,16 +166,16 @@
     }
     if (allocator.isReady()) {  // Did not use pixels!
         SkBitmap bm;
-        SkASSERT(bitmap.canCopyTo(fRequestedConfig));
-        if (!bitmap.copyTo(&bm, fRequestedConfig, &allocator)
-            || allocator.isReady()) {
+        SkASSERT(bitmap.canCopyTo(info.colorType()));
+        bool copySuccess = bitmap.copyTo(&bm, info.colorType(), &allocator);
+        if (!copySuccess || allocator.isReady()) {
             SkDEBUGFAIL("bitmap.copyTo(requestedConfig) failed.");
             // Earlier we checked canCopyto(); we expect consistency.
             return false;
         }
-        SkASSERT(check_alpha(fInfo.fAlphaType, bm.alphaType()));
+        SkASSERT(check_alpha(info.alphaType(), bm.alphaType()));
     } else {
-        SkASSERT(check_alpha(fInfo.fAlphaType, bitmap.alphaType()));
+        SkASSERT(check_alpha(info.alphaType(), bitmap.alphaType()));
     }
     return true;
 }
@@ -245,38 +234,23 @@
         return NULL;
     }
 
-    SkImageInfo info;
-    SkBitmap::Config config;
+    SkImageInfo info = bitmap.info();
 
     if (!opts.fUseRequestedColorType) {
-        // Use default config.
-        if (SkBitmap::kIndex8_Config == bitmap.config()) {
+        // Use default
+        if (kIndex_8_SkColorType == bitmap.colorType()) {
             // 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);
+        if (!bitmap.canCopyTo(opts.fRequestedColorType)) {
+            SkASSERT(bitmap.colorType() != opts.fRequestedColorType);
             return NULL;  // Can not translate to needed config.
         }
-        info.fWidth = bitmap.width();
-        info.fHeight = bitmap.height();
         info.fColorType = opts.fRequestedColorType;
-        info.fAlphaType = bitmap.alphaType();
     }
     return SkNEW_ARGS(SkDecodingImageGenerator,
                       (data, autoStream.detach(), info,
-                       opts.fSampleSize, opts.fDitherImage, config));
+                       opts.fSampleSize, opts.fDitherImage));
 }