Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / images / SkDecodingImageGenerator.cpp
index 2d93eb5..3b5cb78 100644 (file)
 #include "SkStream.h"
 #include "SkUtils.h"
 
-static bool equal_modulo_alpha(const SkImageInfo& a, const SkImageInfo& b) {
+namespace {
+bool equal_modulo_alpha(const SkImageInfo& a, const SkImageInfo& b) {
     return a.width() == b.width() && a.height() == b.height() &&
            a.colorType() == b.colorType();
 }
 
-namespace {
+class DecodingImageGenerator : public SkImageGenerator {
+public:
+    virtual ~DecodingImageGenerator();
+
+    SkData*                fData;
+    SkStreamRewindable*    fStream;
+    const SkImageInfo      fInfo;
+    const int              fSampleSize;
+    const bool             fDitherImage;
+
+    DecodingImageGenerator(SkData* data,
+                           SkStreamRewindable* stream,
+                           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;
+};
+
 /**
  *  Special allocator used by getPixels(). Uses preallocated memory
  *  provided if possible, else fall-back on the default allocator
@@ -39,13 +69,13 @@ public:
     virtual bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) {
         if (NULL == fTarget || !equal_modulo_alpha(fInfo, bm->info())) {
             // Call default allocator.
-            return bm->allocPixels(NULL, ct);
+            return bm->tryAllocPixels(NULL, ct);
         }
 
         // 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;
@@ -76,10 +106,9 @@ inline bool check_alpha(SkAlphaType reported, SkAlphaType actual) {
 }
 #endif  // SK_DEBUG
 
-}  // namespace
 ////////////////////////////////////////////////////////////////////////////////
 
-SkDecodingImageGenerator::SkDecodingImageGenerator(
+DecodingImageGenerator::DecodingImageGenerator(
         SkData* data,
         SkStreamRewindable* stream,
         const SkImageInfo& info,
@@ -95,55 +124,37 @@ SkDecodingImageGenerator::SkDecodingImageGenerator(
     SkSafeRef(fData);  // may be NULL.
 }
 
-SkDecodingImageGenerator::~SkDecodingImageGenerator() {
+DecodingImageGenerator::~DecodingImageGenerator() {
     SkSafeUnref(fData);
     fStream->unref();
 }
 
-bool SkDecodingImageGenerator::getInfo(SkImageInfo* info) {
-    if (info != NULL) {
-        *info = fInfo;
-    }
-    return true;
-}
-
-SkData* SkDecodingImageGenerator::refEncodedData() {
+SkData* DecodingImageGenerator::onRefEncodedData() {
     // This functionality is used in `gm --serialize`
     // Does not encode options.
-    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;
+    if (NULL == 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 (length) {
+            fData = SkData::NewFromStream(fStream, length);
+        }
     }
-    void* buffer = sk_malloc_flags(length, 0);
-    SkCheckResult(fStream->read(buffer, length), length);
-    fData = SkData::NewFromMalloc(buffer, length);
     return SkSafeRef(fData);
 }
 
-bool SkDecodingImageGenerator::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));
@@ -152,13 +163,12 @@ bool SkDecodingImageGenerator::getPixels(const SkImageInfo& info,
     }
     decoder->setDitherImage(fDitherImage);
     decoder->setSampleSize(fSampleSize);
+    decoder->setRequireUnpremultipliedColors(info.alphaType() == kUnpremul_SkAlphaType);
 
     SkBitmap bitmap;
     TargetAllocator allocator(fInfo, pixels, rowBytes);
     decoder->setAllocator(&allocator);
-    // TODO: need to be able to pass colortype directly to decoder
-    SkBitmap::Config legacyConfig = SkColorTypeToBitmapConfig(info.colorType());
-    bool success = decoder->decode(fStream, &bitmap, legacyConfig,
+    bool success = decoder->decode(fStream, &bitmap, info.colorType(),
                                    SkImageDecoder::kDecodePixels_Mode);
     decoder->setAllocator(NULL);
     if (!success) {
@@ -177,48 +187,32 @@ bool SkDecodingImageGenerator::getPixels(const SkImageInfo& info,
     } else {
         SkASSERT(check_alpha(info.alphaType(), bitmap.alphaType()));
     }
-    return true;
-}
 
-SkImageGenerator* SkDecodingImageGenerator::Create(
-        SkData* data,
-        const SkDecodingImageGenerator::Options& opts) {
-    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);
-}
-
-SkImageGenerator* SkDecodingImageGenerator::Create(
-        SkStreamRewindable* stream,
-        const SkDecodingImageGenerator::Options& opts) {
-    SkASSERT(stream != NULL);
-    SkASSERT(stream->unique());
-    if ((stream == NULL) || !stream->unique()) {
-        SkSafeUnref(stream);
-        return NULL;
+    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 SkDecodingImageGenerator::Create(NULL, stream, opts);
+    return true;
 }
 
 // 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(
+SkImageGenerator* CreateDecodingImageGenerator(
         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()) {
@@ -226,31 +220,63 @@ SkImageGenerator* SkDecodingImageGenerator::Create(
     }
     SkBitmap bitmap;
     decoder->setSampleSize(opts.fSampleSize);
-    if (!decoder->decode(stream, &bitmap,
-                         SkImageDecoder::kDecodeBounds_Mode)) {
+    decoder->setRequireUnpremultipliedColors(opts.fRequireUnpremul);
+    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 = kPMColor_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.
         }
-        info.fColorType = opts.fRequestedColorType;
+        info = info.makeColorType(opts.fRequestedColorType);
+    }
+
+    if (opts.fRequireUnpremul && info.alphaType() != kOpaque_SkAlphaType) {
+        info = info.makeAlphaType(kUnpremul_SkAlphaType);
+    }
+
+    SkAlphaType newAlphaType = info.alphaType();
+    if (!SkColorTypeValidateAlphaType(info.colorType(), info.alphaType(), &newAlphaType)) {
+        return NULL;
     }
-    return SkNEW_ARGS(SkDecodingImageGenerator,
-                      (data, autoStream.detach(), info,
+
+    return SkNEW_ARGS(DecodingImageGenerator,
+                      (data, autoStream.detach(), info.makeAlphaType(newAlphaType),
                        opts.fSampleSize, opts.fDitherImage));
 }
+
+}  // namespace
+
+////////////////////////////////////////////////////////////////////////////////
+
+SkImageGenerator* SkDecodingImageGenerator::Create(
+        SkData* data,
+        const SkDecodingImageGenerator::Options& opts) {
+    SkASSERT(data != NULL);
+    if (NULL == data) {
+        return NULL;
+    }
+    SkStreamRewindable* stream = SkNEW_ARGS(SkMemoryStream, (data));
+    SkASSERT(stream != NULL);
+    SkASSERT(stream->unique());
+    return CreateDecodingImageGenerator(data, stream, opts);
+}
+
+SkImageGenerator* SkDecodingImageGenerator::Create(
+        SkStreamRewindable* stream,
+        const SkDecodingImageGenerator::Options& opts) {
+    SkASSERT(stream != NULL);
+    SkASSERT(stream->unique());
+    if ((stream == NULL) || !stream->unique()) {
+        SkSafeUnref(stream);
+        return NULL;
+    }
+    return CreateDecodingImageGenerator(NULL, stream, opts);
+}