| Index: src/images/SkDecodingImageGenerator.cpp
|
| diff --git a/src/images/SkDecodingImageGenerator.cpp b/src/images/SkDecodingImageGenerator.cpp
|
| index 153d1e220bc6be643dea492e8c4d74192872268c..a833c636ff9c8d30df1c1ade660743ea8b2a47d2 100644
|
| --- a/src/images/SkDecodingImageGenerator.cpp
|
| +++ b/src/images/SkDecodingImageGenerator.cpp
|
| @@ -5,14 +5,13 @@
|
| * found in the LICENSE file.
|
| */
|
|
|
| +#include "SkDecodingImageGenerator.h"
|
| #include "SkData.h"
|
| -#include "SkDecodingImageGenerator.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) { }
|
| -
|
| - 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);
|
| + , 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;
|
| }
|
| - // 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.
|
| - 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 (!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;
|
| }
|
| - 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(dst != NULL);
|
| + SkImageGenerator* gen(SkNEW_ARGS(SkDecodingImageGenerator, (data)));
|
| + return SkInstallDiscardablePixelRef(gen, dst, factory);
|
| +}
|
| +
|
| +bool SkDecodingImageGenerator::Install(SkStreamRewindable* stream,
|
| + SkBitmap* dst,
|
| + SkDiscardableMemory::Factory* factory) {
|
| 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());
|
| + SkASSERT(dst != NULL);
|
| if ((stream == NULL) || !stream->unique()) {
|
| SkSafeUnref(stream);
|
| - return NULL;
|
| - }
|
| - 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));
|
| -}
|
| + return false;
|
| + }
|
| + SkImageGenerator* gen(SkNEW_ARGS(SkDecodingImageGenerator, (stream)));
|
| + return SkInstallDiscardablePixelRef(gen, dst, factory);
|
| +}
|
|
|