Revert "Revert of add colortable support to imagegenerator (https://codereview.chromium.org/304443003/)"

Fix is to add colortable param to installPixels()

This reverts commit 924205aaf2e0c3c65dda13e0eaccde3e7b2a5c40.

BUG=skia:
R=scroggo@google.com, reed@chromium.org

Author: reed@google.com

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

git-svn-id: http://skia.googlecode.com/svn/trunk@14958 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp
index a89ca35..0bfcb6f 100644
--- a/src/core/SkBitmap.cpp
+++ b/src/core/SkBitmap.cpp
@@ -442,16 +442,14 @@
     return true;
 }
 
-bool SkBitmap::installPixels(const SkImageInfo& info, void* pixels, size_t rb,
-                             void (*releaseProc)(void* addr, void* context),
-                             void* context) {
+bool SkBitmap::installPixels(const SkImageInfo& info, void* pixels, size_t rb, SkColorTable* ct,
+                             void (*releaseProc)(void* addr, void* context), void* context) {
     if (!this->setConfig(info, rb)) {
         this->reset();
         return false;
     }
 
-    SkPixelRef* pr = SkMallocPixelRef::NewWithProc(info, rb, NULL, pixels,
-                                                   releaseProc, context);
+    SkPixelRef* pr = SkMallocPixelRef::NewWithProc(info, rb, ct, pixels, releaseProc, context);
     if (!pr) {
         this->reset();
         return false;
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 6500212..7e10504 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -1114,8 +1114,7 @@
 
 bool SkAutoROCanvasPixels::asROBitmap(SkBitmap* bitmap) const {
     if (fAddr) {
-        return bitmap->installPixels(fInfo, const_cast<void*>(fAddr), fRowBytes,
-                                     NULL, NULL);
+        return bitmap->installPixels(fInfo, const_cast<void*>(fAddr), fRowBytes);
     } else {
         bitmap->reset();
         return false;
diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp
index b0af040..aaf4235 100644
--- a/src/effects/SkBlurMaskFilter.cpp
+++ b/src/effects/SkBlurMaskFilter.cpp
@@ -242,7 +242,7 @@
                                            mask->fBounds.height(),
                                            kAlpha_8_SkColorType,
                                            kPremul_SkAlphaType),
-                         mask->fImage, mask->fRowBytes, NULL, NULL);
+                         mask->fImage, mask->fRowBytes);
 
     SkCanvas canvas(bitmap);
     canvas.translate(-SkIntToScalar(mask->fBounds.left()),
diff --git a/src/image/SkImage_Raster.cpp b/src/image/SkImage_Raster.cpp
index 7a8091c..3be7d84 100644
--- a/src/image/SkImage_Raster.cpp
+++ b/src/image/SkImage_Raster.cpp
@@ -94,8 +94,9 @@
 {
     data->ref();
     void* addr = const_cast<void*>(data->data());
+    SkColorTable* ctable = NULL;
 
-    fBitmap.installPixels(info, addr, rowBytes, release_data, data);
+    fBitmap.installPixels(info, addr, rowBytes, ctable, release_data, data);
     fBitmap.setImmutable();
     fBitmap.lockPixels();
 }
diff --git a/src/images/SkDecodingImageGenerator.cpp b/src/images/SkDecodingImageGenerator.cpp
index b3924a7..2493d89 100644
--- a/src/images/SkDecodingImageGenerator.cpp
+++ b/src/images/SkDecodingImageGenerator.cpp
@@ -23,12 +23,6 @@
 class DecodingImageGenerator : public SkImageGenerator {
 public:
     virtual ~DecodingImageGenerator();
-    virtual SkData* refEncodedData() SK_OVERRIDE;
-    // This implementaion of getInfo() always returns true.
-    virtual bool getInfo(SkImageInfo* info) SK_OVERRIDE;
-    virtual bool getPixels(const SkImageInfo& info,
-                           void* pixels,
-                           size_t rowBytes) SK_OVERRIDE;
 
     SkData*                fData;
     SkStreamRewindable*    fStream;
@@ -41,6 +35,18 @@
                            const SkImageInfo& info,
                            int sampleSize,
                            bool ditherImage);
+
+protected:
+    virtual SkData* onRefEncodedData() SK_OVERRIDE;
+    virtual bool onGetInfo(SkImageInfo* info) SK_OVERRIDE {
+        *info = fInfo;
+        return true;
+    }
+    virtual bool onGetPixels(const SkImageInfo& info,
+                             void* pixels, size_t rowBytes,
+                             SkPMColor ctable[], int* ctableCount) SK_OVERRIDE;
+
+private:
     typedef SkImageGenerator INHERITED;
 };
 
@@ -69,7 +75,7 @@
         // TODO(halcanary): verify that all callers of this function
         // will respect new RowBytes.  Will be moot once rowbytes belongs
         // to PixelRef.
-        bm->installPixels(fInfo, fTarget, fRowBytes, NULL, NULL);
+        bm->installPixels(fInfo, fTarget, fRowBytes, ct, NULL, NULL);
 
         fTarget = NULL;  // never alloc same pixels twice!
         return true;
@@ -123,14 +129,7 @@
     fStream->unref();
 }
 
-bool DecodingImageGenerator::getInfo(SkImageInfo* info) {
-    if (info != NULL) {
-        *info = fInfo;
-    }
-    return true;
-}
-
-SkData* DecodingImageGenerator::refEncodedData() {
+SkData* DecodingImageGenerator::onRefEncodedData() {
     // This functionality is used in `gm --serialize`
     // Does not encode options.
     if (fData != NULL) {
@@ -151,22 +150,15 @@
     return SkSafeRef(fData);
 }
 
-bool DecodingImageGenerator::getPixels(const SkImageInfo& info,
-                                         void* pixels,
-                                         size_t rowBytes) {
-    if (NULL == pixels) {
-        return false;
-    }
+bool DecodingImageGenerator::onGetPixels(const SkImageInfo& info,
+                                         void* pixels, size_t rowBytes,
+                                         SkPMColor ctableEntries[], int* ctableCount) {
     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.
         return false;
     }
-    if (info.minRowBytes() > rowBytes) {
-        // The caller has specified a bad rowBytes.
-        return false;
-    }
 
     SkAssertResult(fStream->rewind());
     SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(fStream));
@@ -202,6 +194,20 @@
     } else {
         SkASSERT(check_alpha(info.alphaType(), bitmap.alphaType()));
     }
+
+    if (kIndex_8_SkColorType == info.colorType()) {
+        if (kIndex_8_SkColorType != bitmap.colorType()) {
+            return false;   // they asked for Index8, but we didn't receive that from decoder
+        }
+        SkColorTable* ctable = bitmap.getColorTable();
+        if (NULL == ctable) {
+            return false;
+        }
+        const int count = ctable->count();
+        memcpy(ctableEntries, ctable->lockColors(), count * sizeof(SkPMColor));
+        ctable->unlockColors();
+        *ctableCount = count;
+    }
     return true;
 }
 
@@ -214,11 +220,6 @@
         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()) {
@@ -227,24 +228,16 @@
     SkBitmap bitmap;
     decoder->setSampleSize(opts.fSampleSize);
     decoder->setRequireUnpremultipliedColors(opts.fRequireUnpremul);
-    if (!decoder->decode(stream, &bitmap,
-                         SkImageDecoder::kDecodeBounds_Mode)) {
+    if (!decoder->decode(stream, &bitmap, SkImageDecoder::kDecodeBounds_Mode)) {
         return NULL;
     }
-    if (bitmap.config() == SkBitmap::kNo_Config) {
+    if (kUnknown_SkColorType == bitmap.colorType()) {
         return NULL;
     }
 
     SkImageInfo info = bitmap.info();
 
-    if (!opts.fUseRequestedColorType) {
-        // Use default
-        if (kIndex_8_SkColorType == bitmap.colorType()) {
-            // We don't support kIndex8 because we don't support
-            // colortables in this workflow.
-            info.fColorType = kN32_SkColorType;
-        }
-    } else {
+    if (opts.fUseRequestedColorType && (opts.fRequestedColorType != info.colorType())) {
         if (!bitmap.canCopyTo(opts.fRequestedColorType)) {
             SkASSERT(bitmap.colorType() != opts.fRequestedColorType);
             return NULL;  // Can not translate to needed config.
diff --git a/src/images/SkImageGenerator.cpp b/src/images/SkImageGenerator.cpp
new file mode 100644
index 0000000..daa55a3
--- /dev/null
+++ b/src/images/SkImageGenerator.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkImageGenerator.h"
+
+#ifndef SK_SUPPORT_LEGACY_IMAGEGENERATORAPI
+bool SkImageGenerator::getInfo(SkImageInfo* info) {
+    SkImageInfo dummy;
+    if (NULL == info) {
+        info = &dummy;
+    }
+    return this->onGetInfo(info);
+}
+
+bool SkImageGenerator::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
+                                 SkPMColor ctable[], int* ctableCount) {
+    if (kUnknown_SkColorType == info.colorType()) {
+        return false;
+    }
+    if (NULL == pixels) {
+        return false;
+    }
+    if (rowBytes < info.minRowBytes()) {
+        return false;
+    }
+
+    if (kIndex_8_SkColorType == info.colorType()) {
+        if (NULL == ctable || NULL == ctableCount) {
+            return false;
+        }
+    } else {
+        if (ctableCount) {
+            *ctableCount = 0;
+        }
+        ctableCount = NULL;
+        ctable = NULL;
+    }
+
+    bool success = this->onGetPixels(info, pixels, rowBytes, ctable, ctableCount);
+
+    if (success && ctableCount) {
+        SkASSERT(*ctableCount >= 0 && *ctableCount <= 256);
+    }
+    return success;
+}
+
+bool SkImageGenerator::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) {
+    SkASSERT(kIndex_8_SkColorType != info.colorType());
+    if (kIndex_8_SkColorType == info.colorType()) {
+        return false;
+    }
+    return this->getPixels(info, pixels, rowBytes, NULL, NULL);
+}
+#endif
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+SkData* SkImageGenerator::onRefEncodedData() {
+    return NULL;
+}
+
+bool SkImageGenerator::onGetInfo(SkImageInfo*) {
+    return false;
+}
+
+bool SkImageGenerator::onGetPixels(const SkImageInfo&, void*, size_t, SkPMColor*, int*) {
+    return false;
+}
diff --git a/src/lazy/SkDiscardablePixelRef.cpp b/src/lazy/SkDiscardablePixelRef.cpp
index ccf812c..b0bbd27 100644
--- a/src/lazy/SkDiscardablePixelRef.cpp
+++ b/src/lazy/SkDiscardablePixelRef.cpp
@@ -60,15 +60,30 @@
     }
 
     void* pixels = fDiscardableMemory->data();
-    if (!fGenerator->getPixels(this->info(), pixels, fRowBytes)) {
+    const SkImageInfo& info = this->info();
+    SkPMColor colors[256];
+    int colorCount = 0;
+
+    if (!fGenerator->getPixels(info, pixels, fRowBytes, colors, &colorCount)) {
         fDiscardableMemory->unlock();
         SkDELETE(fDiscardableMemory);
         fDiscardableMemory = NULL;
         return false;
     }
 
+    // Note: our ctable is not purgable, as it is not stored in the discardablememory block.
+    // This is because SkColorTable is refcntable, and therefore our caller could hold onto it
+    // beyond the scope of a lock/unlock. If we change the API/lifecycle for SkColorTable, we
+    // could move it into the block, but then again perhaps it is small enough that this doesn't
+    // really matter.
+    if (colorCount > 0) {
+        fCTable.reset(SkNEW_ARGS(SkColorTable, (colors, colorCount)));
+    } else {
+        fCTable.reset(NULL);
+    }
+
     rec->fPixels = pixels;
-    rec->fColorTable = NULL;
+    rec->fColorTable = fCTable.get();
     rec->fRowBytes = fRowBytes;
     return true;
 }
diff --git a/src/lazy/SkDiscardablePixelRef.h b/src/lazy/SkDiscardablePixelRef.h
index e5e1c9f..52a1d6c 100644
--- a/src/lazy/SkDiscardablePixelRef.h
+++ b/src/lazy/SkDiscardablePixelRef.h
@@ -17,10 +17,6 @@
  *  A PixelRef backed by SkDiscardableMemory, with the ability to
  *  re-generate the pixels (via a SkImageGenerator) if the DM is
  *  purged.
- *
- *  Since SkColorTable is reference-counted, we do not support indexed
- *  color with this class; there would be no way for the discardable
- *  memory system to unref the color table.
  */
 class SkDiscardablePixelRef : public SkPixelRef {
 public:
@@ -46,6 +42,7 @@
     // PixelRef, since the SkBitmap doesn't expect them to change.
 
     SkDiscardableMemory* fDiscardableMemory;
+    SkAutoTUnref<SkColorTable> fCTable;
 
     /* Takes ownership of SkImageGenerator. */
     SkDiscardablePixelRef(const SkImageInfo&, SkImageGenerator*,
diff --git a/src/utils/SkCanvasStateUtils.cpp b/src/utils/SkCanvasStateUtils.cpp
index 64f62dd..eaee61b 100644
--- a/src/utils/SkCanvasStateUtils.cpp
+++ b/src/utils/SkCanvasStateUtils.cpp
@@ -291,8 +291,7 @@
 
     bitmap.installPixels(SkImageInfo::Make(layerState.width, layerState.height,
                                            colorType, kPremul_SkAlphaType),
-                         layerState.raster.pixels, layerState.raster.rowBytes,
-                         NULL, NULL);
+                         layerState.raster.pixels, layerState.raster.rowBytes);
 
     SkASSERT(!bitmap.empty());
     SkASSERT(!bitmap.isNull());