diff options
author | Jocelyn Turcotte <jocelyn.turcotte@digia.com> | 2014-08-08 14:30:41 +0200 |
---|---|---|
committer | Jocelyn Turcotte <jocelyn.turcotte@digia.com> | 2014-08-12 13:49:54 +0200 |
commit | ab0a50979b9eb4dfa3320eff7e187e41efedf7a9 (patch) | |
tree | 498dfb8a97ff3361a9f7486863a52bb4e26bb898 /chromium/third_party/skia/src/images | |
parent | 4ce69f7403811819800e7c5ae1318b2647e778d1 (diff) |
Update Chromium to beta version 37.0.2062.68
Change-Id: I188e3b5aff1bec75566014291b654eb19f5bc8ca
Reviewed-by: Andras Becsi <andras.becsi@digia.com>
Diffstat (limited to 'chromium/third_party/skia/src/images')
26 files changed, 1126 insertions, 1401 deletions
diff --git a/chromium/third_party/skia/src/images/SkDecodingImageGenerator.cpp b/chromium/third_party/skia/src/images/SkDecodingImageGenerator.cpp index a833c636ff9..88cdef9a321 100644 --- a/chromium/third_party/skia/src/images/SkDecodingImageGenerator.cpp +++ b/chromium/third_party/skia/src/images/SkDecodingImageGenerator.cpp @@ -5,81 +5,133 @@ * 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 { +bool equal_modulo_alpha(const SkImageInfo& a, const SkImageInfo& b) { + return a.width() == b.width() && a.height() == b.height() && + a.colorType() == b.colorType(); +} + +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. + * provided if possible, else fall-back on the default allocator */ class TargetAllocator : public SkBitmap::Allocator { public: - TargetAllocator(void* target, size_t rowBytes, const SkImageInfo& info) - : fTarget(target) + TargetAllocator(const SkImageInfo& info, + void* target, + size_t rowBytes) + : fInfo(info) + , fTarget(target) , fRowBytes(rowBytes) - , 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; + bool isReady() { return (fTarget != NULL); } + + virtual bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) { + if (NULL == fTarget || !equal_modulo_alpha(fInfo, bm->info())) { + // Call default allocator. + return bm->allocPixels(NULL, ct); } - bm->setConfig(bm->config(), bm->width(), bm->height(), - fRowBytes, bm->alphaType()); - bm->setPixels(fTarget, 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, ct, NULL, NULL); + + fTarget = NULL; // never alloc same pixels twice! return true; } private: - void* fTarget; - size_t fRowBytes; - SkImageInfo fInfo; + 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 fInfo and fRowBytes + const size_t fRowBytes; // rowbytes for the destination bitmap + 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(); +// TODO(halcanary): Give this macro a better name and move it into SkTypes.h +#ifdef SK_DEBUG + #define SkCheckResult(expr, value) SkASSERT((value) == (expr)) +#else + #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 + +//////////////////////////////////////////////////////////////////////////////// -SkDecodingImageGenerator::SkDecodingImageGenerator(SkStreamRewindable* stream) - : fData(NULL) +DecodingImageGenerator::DecodingImageGenerator( + SkData* data, + SkStreamRewindable* stream, + const SkImageInfo& info, + int sampleSize, + bool ditherImage) + : fData(data) , fStream(stream) - , fHasInfo(false) - , fDoCopyTo(false) { - SkASSERT(fStream != NULL); - SkASSERT(fStream->unique()); + , fInfo(info) + , fSampleSize(sampleSize) + , fDitherImage(ditherImage) +{ + SkASSERT(stream != NULL); + SkSafeRef(fData); // may be NULL. } -SkDecodingImageGenerator::~SkDecodingImageGenerator() { +DecodingImageGenerator::~DecodingImageGenerator() { SkSafeUnref(fData); fStream->unref(); } -// TODO(halcanary): Give this macro a better name and move it into SkTypes.h -#ifdef SK_DEBUG - #define SkCheckResult(expr, value) SkASSERT((value) == (expr)) -#else - #define SkCheckResult(expr, value) (void)(expr) -#endif - -SkData* SkDecodingImageGenerator::refEncodedData() { +SkData* DecodingImageGenerator::onRefEncodedData() { // This functionality is used in `gm --serialize` + // Does not encode options. if (fData != NULL) { return SkSafeRef(fData); } @@ -98,111 +150,132 @@ SkData* SkDecodingImageGenerator::refEncodedData() { 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; +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; } + SkAssertResult(fStream->rewind()); SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(fStream)); if (NULL == decoder.get()) { return false; } + decoder->setDitherImage(fDitherImage); + decoder->setSampleSize(fSampleSize); + decoder->setRequireUnpremultipliedColors( + info.fAlphaType == kUnpremul_SkAlphaType); + SkBitmap bitmap; - if (!decoder->decode(fStream, &bitmap, - SkImageDecoder::kDecodeBounds_Mode)) { - return false; - } - if (bitmap.config() == SkBitmap::kNo_Config) { + TargetAllocator allocator(fInfo, pixels, rowBytes); + decoder->setAllocator(&allocator); + bool success = decoder->decode(fStream, &bitmap, info.colorType(), + SkImageDecoder::kDecodePixels_Mode); + decoder->setAllocator(NULL); + if (!success) { 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)"); + if (allocator.isReady()) { // Did not use pixels! + SkBitmap bm; + 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; } - fDoCopyTo = true; - fInfo.fWidth = bitmap.width(); - fInfo.fHeight = bitmap.height(); - fInfo.fColorType = kPMColor_SkColorType; - fInfo.fAlphaType = bitmap.alphaType(); + SkASSERT(check_alpha(info.alphaType(), bm.alphaType())); + } else { + SkASSERT(check_alpha(info.alphaType(), bitmap.alphaType())); } - if (info != NULL) { - *info = fInfo; + + 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; } - fHasInfo = true; return true; } -bool SkDecodingImageGenerator::getPixels(const SkImageInfo& info, - void* pixels, - size_t rowBytes) { - if (NULL == pixels) { - 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)); +// 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* CreateDecodingImageGenerator( + SkData* data, + SkStreamRewindable* stream, + const SkDecodingImageGenerator::Options& opts) { + SkASSERT(stream); + SkAutoTUnref<SkStreamRewindable> autoStream(stream); // always unref this. + SkAssertResult(autoStream->rewind()); + SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(autoStream)); if (NULL == decoder.get()) { - return false; - } - 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; + return NULL; } SkBitmap bitmap; - if (!bitmap.setConfig(info, rowBytes)) { - return false; + decoder->setSampleSize(opts.fSampleSize); + decoder->setRequireUnpremultipliedColors(opts.fRequireUnpremul); + if (!decoder->decode(stream, &bitmap, SkImageDecoder::kDecodeBounds_Mode)) { + return NULL; } - - TargetAllocator allocator(pixels, rowBytes, info); - if (!fDoCopyTo) { - decoder->setAllocator(&allocator); + if (kUnknown_SkColorType == bitmap.colorType()) { + return NULL; } - bool success = decoder->decode(fStream, &bitmap, - SkImageDecoder::kDecodePixels_Mode); - decoder->setAllocator(NULL); - if (!success) { - return false; + + SkImageInfo info = bitmap.info(); + + 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; } - if (fDoCopyTo) { - SkBitmap bm8888; - bitmap.copyTo(&bm8888, SkBitmap::kARGB_8888_Config, &allocator); + + if (opts.fRequireUnpremul && info.fAlphaType != kOpaque_SkAlphaType) { + info.fAlphaType = kUnpremul_SkAlphaType; } - return true; + return SkNEW_ARGS(DecodingImageGenerator, + (data, autoStream.detach(), info, + opts.fSampleSize, opts.fDitherImage)); } -bool SkDecodingImageGenerator::Install(SkData* data, SkBitmap* dst, - SkDiscardableMemory::Factory* factory) { + +} // namespace + +//////////////////////////////////////////////////////////////////////////////// + +SkImageGenerator* SkDecodingImageGenerator::Create( + SkData* data, + const SkDecodingImageGenerator::Options& opts) { SkASSERT(data != NULL); - SkASSERT(dst != NULL); - SkImageGenerator* gen(SkNEW_ARGS(SkDecodingImageGenerator, (data))); - return SkInstallDiscardablePixelRef(gen, dst, factory); + if (NULL == data) { + return NULL; + } + SkStreamRewindable* stream = SkNEW_ARGS(SkMemoryStream, (data)); + SkASSERT(stream != NULL); + SkASSERT(stream->unique()); + return CreateDecodingImageGenerator(data, stream, opts); } -bool SkDecodingImageGenerator::Install(SkStreamRewindable* stream, - SkBitmap* dst, - SkDiscardableMemory::Factory* factory) { +SkImageGenerator* SkDecodingImageGenerator::Create( + SkStreamRewindable* stream, + const SkDecodingImageGenerator::Options& opts) { SkASSERT(stream != NULL); - SkASSERT(dst != NULL); + SkASSERT(stream->unique()); if ((stream == NULL) || !stream->unique()) { SkSafeUnref(stream); - return false; + return NULL; } - SkImageGenerator* gen(SkNEW_ARGS(SkDecodingImageGenerator, (stream))); - return SkInstallDiscardablePixelRef(gen, dst, factory); + return CreateDecodingImageGenerator(NULL, stream, opts); } diff --git a/chromium/third_party/skia/src/images/SkDecodingImageGenerator.h b/chromium/third_party/skia/src/images/SkDecodingImageGenerator.h deleted file mode 100644 index dba234bcf19..00000000000 --- a/chromium/third_party/skia/src/images/SkDecodingImageGenerator.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright 2013 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef SkDecodingImageGenerator_DEFINED -#define SkDecodingImageGenerator_DEFINED - -#include "SkDiscardableMemory.h" -#include "SkImageGenerator.h" -#include "SkImageInfo.h" - -class SkBitmap; -class SkStreamRewindable; - -/** - * Calls into SkImageDecoder::DecodeMemoryToTarget to implement a - * SkImageGenerator - */ -class SkDecodingImageGenerator : public SkImageGenerator { -public: - /* - * The constructor will take a reference to the SkData. The - * destructor will unref() it. - */ - explicit SkDecodingImageGenerator(SkData* data); - - /* - * The SkData version of this constructor is preferred. If the - * stream has an underlying SkData (such as a SkMemoryStream) - * pass that in. - * - * This object will unref the stream when done. Since streams - * have internal state (position), the caller should not pass a - * shared stream in. Pass either a new duplicated stream in or - * transfer ownership of the stream. In the latter case, be sure - * that there are no other consumers of the stream who will - * modify the stream's position. This constructor asserts - * stream->unique(). - * - * For example: - * SkStreamRewindable* stream; - * ... - * SkImageGenerator* gen - * = SkNEW_ARGS(SkDecodingImageGenerator, - * (stream->duplicate())); - * ... - * SkDELETE(gen); - */ - explicit SkDecodingImageGenerator(SkStreamRewindable* stream); - - virtual ~SkDecodingImageGenerator(); - - virtual SkData* refEncodedData() SK_OVERRIDE; - - virtual bool getInfo(SkImageInfo* info) SK_OVERRIDE; - - virtual bool getPixels(const SkImageInfo& info, - void* pixels, - size_t rowBytes) SK_OVERRIDE; - - /** - * Install the SkData into the destination bitmap, using a new - * SkDiscardablePixelRef and a new SkDecodingImageGenerator. - * - * @param data Contains the encoded image data that will be used - * by the SkDecodingImageGenerator. Will be ref()ed. - * - * @param destination Upon success, this bitmap will be - * configured and have a pixelref installed. - * - * @param factory If not NULL, this object will be used as a - * source of discardable memory when decoding. If NULL, then - * SkDiscardableMemory::Create() will be called. - * - * @return true iff successful. - */ - static bool Install(SkData* data, SkBitmap* destination, - SkDiscardableMemory::Factory* factory = NULL); - /** - * Install the stream into the destination bitmap, using a new - * SkDiscardablePixelRef and a new SkDecodingImageGenerator. - * - * The SkData version of this function is preferred. If the - * stream has an underlying SkData (such as a SkMemoryStream) - * pass that in. - * - * @param stream The source of encoded data that will be passed - * to the decoder. The installed SkDecodingImageGenerator will - * unref the stream when done. If false is returned, this - * function will perform the unref. Since streams have internal - * state (position), the caller should not pass a shared stream - * in. Pass either a new duplicated stream in or transfer - * ownership of the stream. In the latter case, be sure that - * there are no other consumers of the stream who will modify the - * stream's position. This function will fail if - * (!stream->unique()). - * - * @param destination Upon success, this bitmap will be - * configured and have a pixelref installed. - * - * @param factory If not NULL, this object will be used as a - * source of discardable memory when decoding. If NULL, then - * SkDiscardableMemory::Create() will be called. - * - * @return true iff successful. - */ - static bool Install(SkStreamRewindable* stream, SkBitmap* destination, - SkDiscardableMemory::Factory* factory = NULL); - -private: - SkData* fData; - SkStreamRewindable* fStream; - SkImageInfo fInfo; - bool fHasInfo; - bool fDoCopyTo; -}; -#endif // SkDecodingImageGenerator_DEFINED diff --git a/chromium/third_party/skia/src/images/SkForceLinking.cpp b/chromium/third_party/skia/src/images/SkForceLinking.cpp index e4dc60a4480..2c9a38979ac 100644 --- a/chromium/third_party/skia/src/images/SkForceLinking.cpp +++ b/chromium/third_party/skia/src/images/SkForceLinking.cpp @@ -18,6 +18,8 @@ int SkForceLinking(bool doNotPassTrue) { CreateWEBPImageDecoder(); CreateBMPImageDecoder(); CreateICOImageDecoder(); + CreatePKMImageDecoder(); + CreateKTXImageDecoder(); CreateWBMPImageDecoder(); // Only link GIF and PNG on platforms that build them. See images.gyp #if !defined(SK_BUILD_FOR_MAC) && !defined(SK_BUILD_FOR_WIN) && !defined(SK_BUILD_FOR_NACL) \ diff --git a/chromium/third_party/skia/src/images/SkImageDecoder.cpp b/chromium/third_party/skia/src/images/SkImageDecoder.cpp index 32cf087ed86..fe61906357d 100644 --- a/chromium/third_party/skia/src/images/SkImageDecoder.cpp +++ b/chromium/third_party/skia/src/images/SkImageDecoder.cpp @@ -14,28 +14,18 @@ #include "SkTemplates.h" #include "SkCanvas.h" -static SkBitmap::Config gDeviceConfig = SkBitmap::kNo_Config; - -SkBitmap::Config SkImageDecoder::GetDeviceConfig() -{ - return gDeviceConfig; -} - -void SkImageDecoder::SetDeviceConfig(SkBitmap::Config config) -{ - gDeviceConfig = config; -} - -/////////////////////////////////////////////////////////////////////////////// - SkImageDecoder::SkImageDecoder() : fPeeker(NULL) +#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER , fChooser(NULL) +#endif , fAllocator(NULL) , fSampleSize(1) - , fDefaultPref(SkBitmap::kNo_Config) + , fDefaultPref(kUnknown_SkColorType) , fDitherImage(true) +#ifdef SK_SUPPORT_LEGACY_BITMAP_CONFIG , fUsePrefTable(false) +#endif , fSkipWritingZeroes(false) , fPreferQualityOverSpeed(false) , fRequireUnpremultipliedColors(false) { @@ -43,7 +33,9 @@ SkImageDecoder::SkImageDecoder() SkImageDecoder::~SkImageDecoder() { SkSafeUnref(fPeeker); +#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER SkSafeUnref(fChooser); +#endif SkSafeUnref(fAllocator); } @@ -52,14 +44,18 @@ void SkImageDecoder::copyFieldsToOther(SkImageDecoder* other) { return; } other->setPeeker(fPeeker); +#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER other->setChooser(fChooser); +#endif other->setAllocator(fAllocator); other->setSampleSize(fSampleSize); +#ifdef SK_SUPPORT_LEGACY_BITMAP_CONFIG if (fUsePrefTable) { other->setPrefConfigTable(fPrefTable); } else { other->fDefaultPref = fDefaultPref; } +#endif other->setDitherImage(fDitherImage); other->setSkipWritingZeroes(fSkipWritingZeroes); other->setPreferQualityOverSpeed(fPreferQualityOverSpeed); @@ -84,6 +80,10 @@ const char* SkImageDecoder::GetFormatName(Format format) { return "GIF"; case kICO_Format: return "ICO"; + case kPKM_Format: + return "PKM"; + case kKTX_Format: + return "KTX"; case kJPEG_Format: return "JPEG"; case kPNG_Format: @@ -103,10 +103,12 @@ SkImageDecoder::Peeker* SkImageDecoder::setPeeker(Peeker* peeker) { return peeker; } +#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER SkImageDecoder::Chooser* SkImageDecoder::setChooser(Chooser* chooser) { SkRefCnt_SafeAssign(fChooser, chooser); return chooser; } +#endif SkBitmap::Allocator* SkImageDecoder::setAllocator(SkBitmap::Allocator* alloc) { SkRefCnt_SafeAssign(fAllocator, alloc); @@ -120,17 +122,20 @@ void SkImageDecoder::setSampleSize(int size) { fSampleSize = size; } -bool SkImageDecoder::chooseFromOneChoice(SkBitmap::Config config, int width, - int height) const { +#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER +// TODO: change Chooser virtual to take colorType, so we can stop calling SkColorTypeToBitmapConfig +// +bool SkImageDecoder::chooseFromOneChoice(SkColorType colorType, int width, int height) const { Chooser* chooser = fChooser; - + if (NULL == chooser) { // no chooser, we just say YES to decoding :) return true; } chooser->begin(1); - chooser->inspect(0, config, width, height); + chooser->inspect(0, SkColorTypeToBitmapConfig(colorType), width, height); return chooser->choose() == 0; } +#endif bool SkImageDecoder::allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) const { @@ -139,16 +144,22 @@ bool SkImageDecoder::allocPixelRef(SkBitmap* bitmap, /////////////////////////////////////////////////////////////////////////////// +#ifdef SK_SUPPORT_LEGACY_BITMAP_CONFIG void SkImageDecoder::setPrefConfigTable(const PrefConfigTable& prefTable) { fUsePrefTable = true; fPrefTable = prefTable; } +#endif -SkBitmap::Config SkImageDecoder::getPrefConfig(SrcDepth srcDepth, - bool srcHasAlpha) const { - SkBitmap::Config config = SkBitmap::kNo_Config; +// TODO: use colortype in fPrefTable, fDefaultPref so we can stop using SkBitmapConfigToColorType() +// +SkColorType SkImageDecoder::getPrefColorType(SrcDepth srcDepth, bool srcHasAlpha) const { + SkColorType ct = fDefaultPref; +#ifdef SK_SUPPORT_LEGACY_BITMAP_CONFIG if (fUsePrefTable) { + // Until we kill or change the PrefTable, we have to go into Config land for a moment. + SkBitmap::Config config = SkBitmap::kNo_Config; switch (srcDepth) { case kIndex_SrcDepth: config = srcHasAlpha ? fPrefTable.fPrefFor_8Index_YesAlpha_src @@ -162,21 +173,17 @@ SkBitmap::Config SkImageDecoder::getPrefConfig(SrcDepth srcDepth, : fPrefTable.fPrefFor_8bpc_NoAlpha_src; break; } - } else { - config = fDefaultPref; - } - - if (SkBitmap::kNo_Config == config) { - config = SkImageDecoder::GetDeviceConfig(); + // now return to SkColorType land + ct = SkBitmapConfigToColorType(config); } - return config; +#endif + return ct; } -bool SkImageDecoder::decode(SkStream* stream, SkBitmap* bm, - SkBitmap::Config pref, Mode mode) { +bool SkImageDecoder::decode(SkStream* stream, SkBitmap* bm, SkColorType pref, Mode mode) { // we reset this to false before calling onDecode fShouldCancelDecode = false; - // assign this, for use by getPrefConfig(), in case fUsePrefTable is false + // assign this, for use by getPrefColorType(), in case fUsePrefTable is false fDefaultPref = pref; // pass a temporary bitmap, so that if we return false, we are assured of @@ -189,18 +196,16 @@ bool SkImageDecoder::decode(SkStream* stream, SkBitmap* bm, return true; } -bool SkImageDecoder::decodeSubset(SkBitmap* bm, const SkIRect& rect, - SkBitmap::Config pref) { +bool SkImageDecoder::decodeSubset(SkBitmap* bm, const SkIRect& rect, SkColorType pref) { // we reset this to false before calling onDecodeSubset fShouldCancelDecode = false; - // assign this, for use by getPrefConfig(), in case fUsePrefTable is false + // assign this, for use by getPrefColorType(), in case fUsePrefTable is false fDefaultPref = pref; return this->onDecodeSubset(bm, rect); } -bool SkImageDecoder::buildTileIndex(SkStreamRewindable* stream, - int *width, int *height) { +bool SkImageDecoder::buildTileIndex(SkStreamRewindable* stream, int *width, int *height) { // we reset this to false before calling onBuildTileIndex fShouldCancelDecode = false; @@ -212,7 +217,7 @@ bool SkImageDecoder::cropBitmap(SkBitmap *dst, SkBitmap *src, int sampleSize, int srcX, int srcY) { int w = width / sampleSize; int h = height / sampleSize; - if (src->config() == SkBitmap::kIndex8_Config) { + if (src->colorType() == kIndex_8_SkColorType) { // kIndex8 does not allow drawing via an SkCanvas, as is done below. // Instead, use extractSubset. Note that this shares the SkPixelRef and // SkColorTable. @@ -228,7 +233,7 @@ bool SkImageDecoder::cropBitmap(SkBitmap *dst, SkBitmap *src, int sampleSize, } // if the destination has no pixels then we must allocate them. if (dst->isNull()) { - dst->setConfig(src->config(), w, h, 0, src->alphaType()); + dst->setInfo(src->info().makeWH(w, h)); if (!this->allocPixelRef(dst, NULL)) { SkDEBUGF(("failed to allocate pixels needed to crop the bitmap")); @@ -256,8 +261,8 @@ bool SkImageDecoder::cropBitmap(SkBitmap *dst, SkBitmap *src, int sampleSize, /////////////////////////////////////////////////////////////////////////////// -bool SkImageDecoder::DecodeFile(const char file[], SkBitmap* bm, - SkBitmap::Config pref, Mode mode, Format* format) { +bool SkImageDecoder::DecodeFile(const char file[], SkBitmap* bm, SkColorType pref, Mode mode, + Format* format) { SkASSERT(file); SkASSERT(bm); @@ -271,8 +276,8 @@ bool SkImageDecoder::DecodeFile(const char file[], SkBitmap* bm, return false; } -bool SkImageDecoder::DecodeMemory(const void* buffer, size_t size, SkBitmap* bm, - SkBitmap::Config pref, Mode mode, Format* format) { +bool SkImageDecoder::DecodeMemory(const void* buffer, size_t size, SkBitmap* bm, SkColorType pref, + Mode mode, Format* format) { if (0 == size) { return false; } @@ -282,9 +287,8 @@ bool SkImageDecoder::DecodeMemory(const void* buffer, size_t size, SkBitmap* bm, return SkImageDecoder::DecodeStream(&stream, bm, pref, mode, format); } -bool SkImageDecoder::DecodeStream(SkStreamRewindable* stream, SkBitmap* bm, - SkBitmap::Config pref, Mode mode, - Format* format) { +bool SkImageDecoder::DecodeStream(SkStreamRewindable* stream, SkBitmap* bm, SkColorType pref, + Mode mode, Format* format) { SkASSERT(stream); SkASSERT(bm); diff --git a/chromium/third_party/skia/src/images/SkImageDecoder_ktx.cpp b/chromium/third_party/skia/src/images/SkImageDecoder_ktx.cpp new file mode 100644 index 00000000000..effc1edcc11 --- /dev/null +++ b/chromium/third_party/skia/src/images/SkImageDecoder_ktx.cpp @@ -0,0 +1,277 @@ +/* + * 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 "SkColorPriv.h" +#include "SkImageDecoder.h" +#include "SkPixelRef.h" +#include "SkScaledBitmapSampler.h" +#include "SkStream.h" +#include "SkStreamHelpers.h" +#include "SkTypes.h" + +#include "ktx.h" +#include "etc1.h" + +///////////////////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////////////////// + +// KTX Image decoder +// --- +// KTX is a general texture data storage file format ratified by the Khronos Group. As an +// overview, a KTX file contains all of the appropriate values needed to fully specify a +// texture in an OpenGL application, including the use of compressed data. +// +// This decoder is meant to be used with an SkDiscardablePixelRef so that GPU backends +// can sniff the data before creating a texture. If they encounter a compressed format +// that they understand, they can then upload the data directly to the GPU. Otherwise, +// they will decode the data into a format that Skia supports. + +class SkKTXImageDecoder : public SkImageDecoder { +public: + SkKTXImageDecoder() { } + + virtual Format getFormat() const SK_OVERRIDE { + return kKTX_Format; + } + +protected: + virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; + +private: + typedef SkImageDecoder INHERITED; +}; + +bool SkKTXImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { + // TODO: Implement SkStream::copyToData() that's cheap for memory and file streams + SkAutoDataUnref data(CopyStreamToData(stream)); + if (NULL == data) { + return false; + } + + SkKTXFile ktxFile(data); + if (!ktxFile.valid()) { + return false; + } + + const unsigned short width = ktxFile.width(); + const unsigned short height = ktxFile.height(); + +#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER + // should we allow the Chooser (if present) to pick a config for us??? + if (!this->chooseFromOneChoice(kN32_SkColorType, width, height)) { + return false; + } +#endif + + // Set a flag if our source is premultiplied alpha + const SkString premulKey("KTXPremultipliedAlpha"); + const bool bSrcIsPremul = ktxFile.getValueForKey(premulKey) == SkString("True"); + + // Setup the sampler... + SkScaledBitmapSampler sampler(width, height, this->getSampleSize()); + + // Determine the alpha of the bitmap... + SkAlphaType alphaType = kOpaque_SkAlphaType; + if (ktxFile.isRGBA8()) { + if (this->getRequireUnpremultipliedColors()) { + alphaType = kUnpremul_SkAlphaType; + // If the client wants unpremul colors and we only have + // premul, then we cannot honor their wish. + if (bSrcIsPremul) { + return false; + } + } else { + alphaType = kPremul_SkAlphaType; + } + } + + // Set the config... + bm->setInfo(SkImageInfo::MakeN32(sampler.scaledWidth(), sampler.scaledHeight(), alphaType)); + if (SkImageDecoder::kDecodeBounds_Mode == mode) { + return true; + } + + // If we've made it this far, then we know how to grok the data. + if (!this->allocPixelRef(bm, NULL)) { + return false; + } + + // Lock the pixels, since we're about to write to them... + SkAutoLockPixels alp(*bm); + + if (ktxFile.isETC1()) { + if (!sampler.begin(bm, SkScaledBitmapSampler::kRGB, *this)) { + return false; + } + + // ETC1 Data is encoded as RGB pixels, so we should extract it as such + int nPixels = width * height; + SkAutoMalloc outRGBData(nPixels * 3); + etc1_byte *outRGBDataPtr = reinterpret_cast<etc1_byte *>(outRGBData.get()); + + // Decode ETC1 + const etc1_byte *buf = reinterpret_cast<const etc1_byte *>(ktxFile.pixelData()); + if (etc1_decode_image(buf, outRGBDataPtr, width, height, 3, width*3)) { + return false; + } + + // Set each of the pixels... + const int srcRowBytes = width * 3; + const int dstHeight = sampler.scaledHeight(); + const uint8_t *srcRow = reinterpret_cast<uint8_t *>(outRGBDataPtr); + srcRow += sampler.srcY0() * srcRowBytes; + for (int y = 0; y < dstHeight; ++y) { + sampler.next(srcRow); + srcRow += sampler.srcDY() * srcRowBytes; + } + + return true; + + } else if (ktxFile.isRGB8()) { + + // Uncompressed RGB data (without alpha) + if (!sampler.begin(bm, SkScaledBitmapSampler::kRGB, *this)) { + return false; + } + + // Just need to read RGB pixels + const int srcRowBytes = width * 3; + const int dstHeight = sampler.scaledHeight(); + const uint8_t *srcRow = reinterpret_cast<const uint8_t *>(ktxFile.pixelData()); + srcRow += sampler.srcY0() * srcRowBytes; + for (int y = 0; y < dstHeight; ++y) { + sampler.next(srcRow); + srcRow += sampler.srcDY() * srcRowBytes; + } + + return true; + + } else if (ktxFile.isRGBA8()) { + + // Uncompressed RGBA data + + // If we know that the image contains premultiplied alpha, then + // we need to turn off the premultiplier + SkScaledBitmapSampler::Options opts (*this); + if (bSrcIsPremul) { + SkASSERT(bm->alphaType() == kPremul_SkAlphaType); + SkASSERT(!this->getRequireUnpremultipliedColors()); + + opts.fPremultiplyAlpha = false; + } + + if (!sampler.begin(bm, SkScaledBitmapSampler::kRGBA, opts)) { + return false; + } + + // Just need to read RGBA pixels + const int srcRowBytes = width * 4; + const int dstHeight = sampler.scaledHeight(); + const uint8_t *srcRow = reinterpret_cast<const uint8_t *>(ktxFile.pixelData()); + srcRow += sampler.srcY0() * srcRowBytes; + for (int y = 0; y < dstHeight; ++y) { + sampler.next(srcRow); + srcRow += sampler.srcDY() * srcRowBytes; + } + + return true; + } + + return false; +} + +/////////////////////////////////////////////////////////////////////////////// + +// KTX Image Encoder +// +// This encoder takes a best guess at how to encode the bitmap passed to it. If +// there is an installed discardable pixel ref with existing PKM data, then we +// will repurpose the existing ETC1 data into a KTX file. If the data contains +// KTX data, then we simply return a copy of the same data. For all other files, +// the underlying KTX library tries to do its best to encode the appropriate +// data specified by the bitmap based on the config. (i.e. kAlpha8_Config will +// be represented as a full resolution 8-bit image dump with the appropriate +// OpenGL defines in the header). + +class SkKTXImageEncoder : public SkImageEncoder { +protected: + virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) SK_OVERRIDE; + +private: + virtual bool encodePKM(SkWStream* stream, const SkData *data); + typedef SkImageEncoder INHERITED; +}; + +bool SkKTXImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bitmap, int) { + SkAutoDataUnref data(bitmap.pixelRef()->refEncodedData()); + + // Is this even encoded data? + if (NULL != data) { + const uint8_t *bytes = data->bytes(); + if (etc1_pkm_is_valid(bytes)) { + return this->encodePKM(stream, data); + } + + // Is it a KTX file?? + if (SkKTXFile::is_ktx(bytes)) { + return stream->write(bytes, data->size()); + } + + // If it's neither a KTX nor a PKM, then we need to + // get at the actual pixels, so fall through and decompress... + } + + return SkKTXFile::WriteBitmapToKTX(stream, bitmap); +} + +bool SkKTXImageEncoder::encodePKM(SkWStream* stream, const SkData *data) { + const uint8_t* bytes = data->bytes(); + SkASSERT(etc1_pkm_is_valid(bytes)); + + etc1_uint32 width = etc1_pkm_get_width(bytes); + etc1_uint32 height = etc1_pkm_get_height(bytes); + + // ETC1 Data is stored as compressed 4x4 pixel blocks, so we must make sure + // that our dimensions are valid. + if (width == 0 || (width & 3) != 0 || height == 0 || (height & 3) != 0) { + return false; + } + + // Advance pointer to etc1 data. + bytes += ETC_PKM_HEADER_SIZE; + + return SkKTXFile::WriteETC1ToKTX(stream, bytes, width, height); +} + +///////////////////////////////////////////////////////////////////////////////////////// +DEFINE_DECODER_CREATOR(KTXImageDecoder); +DEFINE_ENCODER_CREATOR(KTXImageEncoder); +///////////////////////////////////////////////////////////////////////////////////////// + +static SkImageDecoder* sk_libktx_dfactory(SkStreamRewindable* stream) { + if (SkKTXFile::is_ktx(stream)) { + return SkNEW(SkKTXImageDecoder); + } + return NULL; +} + +static SkImageDecoder::Format get_format_ktx(SkStreamRewindable* stream) { + if (SkKTXFile::is_ktx(stream)) { + return SkImageDecoder::kKTX_Format; + } + return SkImageDecoder::kUnknown_Format; +} + +SkImageEncoder* sk_libktx_efactory(SkImageEncoder::Type t) { + return (SkImageEncoder::kKTX_Type == t) ? SkNEW(SkKTXImageEncoder) : NULL; +} + +static SkImageDecoder_DecodeReg gReg(sk_libktx_dfactory); +static SkImageDecoder_FormatReg gFormatReg(get_format_ktx); +static SkImageEncoder_EncodeReg gEReg(sk_libktx_efactory); diff --git a/chromium/third_party/skia/src/images/SkImageDecoder_libbmp.cpp b/chromium/third_party/skia/src/images/SkImageDecoder_libbmp.cpp index 34a88ac6b00..f9dd2472a0b 100644 --- a/chromium/third_party/skia/src/images/SkImageDecoder_libbmp.cpp +++ b/chromium/third_party/skia/src/images/SkImageDecoder_libbmp.cpp @@ -123,18 +123,17 @@ bool SkBMPImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { int width = callback.width(); int height = callback.height(); - SkBitmap::Config config = this->getPrefConfig(k32Bit_SrcDepth, false); + SkColorType colorType = this->getPrefColorType(k32Bit_SrcDepth, false); // only accept prefConfig if it makes sense for us - if (SkBitmap::kARGB_4444_Config != config && - SkBitmap::kRGB_565_Config != config) { - config = SkBitmap::kARGB_8888_Config; + if (kARGB_4444_SkColorType != colorType && kRGB_565_SkColorType != colorType) { + colorType = kN32_SkColorType; } SkScaledBitmapSampler sampler(width, height, getSampleSize()); - bm->setConfig(config, sampler.scaledWidth(), sampler.scaledHeight(), 0, - kOpaque_SkAlphaType); + bm->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(), + colorType, kOpaque_SkAlphaType)); if (justBounds) { return true; diff --git a/chromium/third_party/skia/src/images/SkImageDecoder_libgif.cpp b/chromium/third_party/skia/src/images/SkImageDecoder_libgif.cpp index f484441c8c3..0c8461f893e 100644 --- a/chromium/third_party/skia/src/images/SkImageDecoder_libgif.cpp +++ b/chromium/third_party/skia/src/images/SkImageDecoder_libgif.cpp @@ -185,6 +185,49 @@ static bool skip_src_rows(GifFileType* gif, uint8_t* dst, int width, int rowsToS return true; } +/** + * GIFs with fewer then 256 color entries will sometimes index out of + * bounds of the color table (this is malformed, but libgif does not + * check sicne it is rare). This function checks for this error and + * fixes it. This makes the output image consistantly deterministic. + */ +static void sanitize_indexed_bitmap(SkBitmap* bm) { + if ((kIndex_8_SkColorType == bm->colorType()) && !(bm->empty())) { + SkAutoLockPixels alp(*bm); + if (NULL != bm->getPixels()) { + SkColorTable* ct = bm->getColorTable(); // Index8 must have it. + SkASSERT(ct != NULL); + uint32_t count = ct->count(); + SkASSERT(count > 0); + SkASSERT(count <= 0x100); + if (count != 0x100) { // Full colortables can't go wrong. + // Count is a power of 2; asserted elsewhere. + uint8_t byteMask = (~(count - 1)); + bool warning = false; + uint8_t* addr = static_cast<uint8_t*>(bm->getPixels()); + int height = bm->height(); + int width = bm->width(); + size_t rowBytes = bm->rowBytes(); + while (--height >= 0) { + uint8_t* ptr = addr; + int x = width; + while (--x >= 0) { + if (0 != ((*ptr) & byteMask)) { + warning = true; + *ptr = 0; + } + ++ptr; + } + addr += rowBytes; + } + if (warning) { + gif_warning(*bm, "Index out of bounds."); + } + } + } + } +} + bool SkGIFImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* bm, Mode mode) { #if GIFLIB_MAJOR < 5 GifFileType* gif = DGifOpen(sk_stream, DecodeCallBackProc); @@ -266,15 +309,17 @@ bool SkGIFImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* bm, Mode mode) { imageTop = 0; } +#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER // FIXME: We could give the caller a choice of images or configs. - if (!this->chooseFromOneChoice(SkBitmap::kIndex8_Config, width, height)) { + if (!this->chooseFromOneChoice(kIndex_8_SkColorType, width, height)) { return error_return(*bm, "chooseFromOneChoice"); } +#endif SkScaledBitmapSampler sampler(width, height, this->getSampleSize()); - bm->setConfig(SkBitmap::kIndex8_Config, sampler.scaledWidth(), - sampler.scaledHeight()); + bm->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(), + kIndex_8_SkColorType, kPremul_SkAlphaType)); if (SkImageDecoder::kDecodeBounds_Mode == mode) { return true; @@ -289,6 +334,7 @@ bool SkGIFImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* bm, Mode mode) { const ColorMapObject* cmap = find_colormap(gif); SkAlphaType alphaType = kOpaque_SkAlphaType; if (cmap != NULL) { + SkASSERT(cmap->ColorCount == (1 << (cmap->BitsPerPixel))); colorCount = cmap->ColorCount; if (colorCount > 256) { colorCount = 256; // our kIndex8 can't support more @@ -410,6 +456,7 @@ bool SkGIFImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* bm, Mode mode) { SkASSERT(read <= innerHeight); skip_src_rows(gif, scanline, innerWidth, innerHeight - read); } + sanitize_indexed_bitmap(bm); return true; } break; @@ -454,6 +501,7 @@ bool SkGIFImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* bm, Mode mode) { } } while (recType != TERMINATE_RECORD_TYPE); + sanitize_indexed_bitmap(bm); return true; } diff --git a/chromium/third_party/skia/src/images/SkImageDecoder_libico.cpp b/chromium/third_party/skia/src/images/SkImageDecoder_libico.cpp index 2b65a36c76f..e6ae16f0bd4 100644 --- a/chromium/third_party/skia/src/images/SkImageDecoder_libico.cpp +++ b/chromium/third_party/skia/src/images/SkImageDecoder_libico.cpp @@ -94,6 +94,7 @@ bool SkICOImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) if (length < (size_t)(6 + count*16)) return false; +#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER int choice; Chooser* chooser = this->getChooser(); //FIXME:if no chooser, consider providing the largest color image @@ -138,6 +139,9 @@ bool SkICOImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) //you never know what the chooser is going to supply if (choice >= count || choice < 0) return false; +#else + const int choice = 0; // TODO: fold this value into the expressions below +#endif //skip ahead to the correct header //commented out lines are not used, but if i switch to other read method, need to know how many to skip @@ -246,7 +250,7 @@ bool SkICOImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) //if the andbitmap (mask) is all zeroes, then we can easily do an index bitmap //however, with small images with large colortables, maybe it's better to still do argb_8888 - bm->setConfig(SkBitmap::kARGB_8888_Config, w, h, calculateRowBytesFor8888(w, bitCount)); + bm->setInfo(SkImageInfo::MakeN32Premul(w, h), calculateRowBytesFor8888(w, bitCount)); if (SkImageDecoder::kDecodeBounds_Mode == mode) { delete[] colors; diff --git a/chromium/third_party/skia/src/images/SkImageDecoder_libjpeg.cpp b/chromium/third_party/skia/src/images/SkImageDecoder_libjpeg.cpp index b08835b5423..9b937162b3e 100644 --- a/chromium/third_party/skia/src/images/SkImageDecoder_libjpeg.cpp +++ b/chromium/third_party/skia/src/images/SkImageDecoder_libjpeg.cpp @@ -248,12 +248,12 @@ private: #endif /** - * Determine the appropriate bitmap config and out_color_space based on + * Determine the appropriate bitmap colortype and out_color_space based on * both the preference of the caller and the jpeg_color_space on the * jpeg_decompress_struct passed in. * Must be called after jpeg_read_header. */ - SkBitmap::Config getBitmapConfig(jpeg_decompress_struct*); + SkColorType getBitmapColorType(jpeg_decompress_struct*); typedef SkImageDecoder INHERITED; }; @@ -400,7 +400,7 @@ static void set_dct_method(const SkImageDecoder& decoder, jpeg_decompress_struct #endif } -SkBitmap::Config SkJPEGImageDecoder::getBitmapConfig(jpeg_decompress_struct* cinfo) { +SkColorType SkJPEGImageDecoder::getBitmapColorType(jpeg_decompress_struct* cinfo) { SkASSERT(cinfo != NULL); SrcDepth srcDepth = k32Bit_SrcDepth; @@ -408,26 +408,26 @@ SkBitmap::Config SkJPEGImageDecoder::getBitmapConfig(jpeg_decompress_struct* cin srcDepth = k8BitGray_SrcDepth; } - SkBitmap::Config config = this->getPrefConfig(srcDepth, /*hasAlpha*/ false); - switch (config) { - case SkBitmap::kA8_Config: - // Only respect A8 config if the original is grayscale, + SkColorType colorType = this->getPrefColorType(srcDepth, /*hasAlpha*/ false); + switch (colorType) { + case kAlpha_8_SkColorType: + // Only respect A8 colortype if the original is grayscale, // in which case we will treat the grayscale as alpha // values. if (cinfo->jpeg_color_space != JCS_GRAYSCALE) { - config = SkBitmap::kARGB_8888_Config; + colorType = kN32_SkColorType; } break; - case SkBitmap::kARGB_8888_Config: + case kN32_SkColorType: // Fall through. - case SkBitmap::kARGB_4444_Config: + case kARGB_4444_SkColorType: // Fall through. - case SkBitmap::kRGB_565_Config: - // These are acceptable destination configs. + case kRGB_565_SkColorType: + // These are acceptable destination colortypes. break; default: - // Force all other configs to 8888. - config = SkBitmap::kARGB_8888_Config; + // Force all other colortypes to 8888. + colorType = kN32_SkColorType; break; } @@ -441,37 +441,37 @@ SkBitmap::Config SkJPEGImageDecoder::getBitmapConfig(jpeg_decompress_struct* cin cinfo->out_color_space = JCS_CMYK; break; case JCS_GRAYSCALE: - if (SkBitmap::kA8_Config == config) { + if (kAlpha_8_SkColorType == colorType) { cinfo->out_color_space = JCS_GRAYSCALE; break; } // The data is JCS_GRAYSCALE, but the caller wants some sort of RGB - // config. Fall through to set to the default. + // colortype. Fall through to set to the default. default: cinfo->out_color_space = JCS_RGB; break; } - return config; + return colorType; } -#ifdef ANDROID_RGB /** - * Based on the config and dither mode, adjust out_color_space and - * dither_mode of cinfo. + * Based on the colortype and dither mode, adjust out_color_space and + * dither_mode of cinfo. Only does work in ANDROID_RGB */ static void adjust_out_color_space_and_dither(jpeg_decompress_struct* cinfo, - SkBitmap::Config config, + SkColorType colorType, const SkImageDecoder& decoder) { SkASSERT(cinfo != NULL); +#ifdef ANDROID_RGB cinfo->dither_mode = JDITHER_NONE; if (JCS_CMYK == cinfo->out_color_space) { return; } - switch(config) { - case SkBitmap::kARGB_8888_Config: + switch (colorType) { + case kN32_SkColorType: cinfo->out_color_space = JCS_RGBA_8888; break; - case SkBitmap::kRGB_565_Config: + case kRGB_565_SkColorType: cinfo->out_color_space = JCS_RGB_565; if (decoder.getDitherImage()) { cinfo->dither_mode = JDITHER_ORDERED; @@ -480,8 +480,8 @@ static void adjust_out_color_space_and_dither(jpeg_decompress_struct* cinfo, default: break; } -} #endif +} /** @@ -569,20 +569,19 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { turn_off_visual_optimizations(&cinfo); - const SkBitmap::Config config = this->getBitmapConfig(&cinfo); + const SkColorType colorType = this->getBitmapColorType(&cinfo); + const SkAlphaType alphaType = kAlpha_8_SkColorType == colorType ? + kPremul_SkAlphaType : kOpaque_SkAlphaType; -#ifdef ANDROID_RGB - adjust_out_color_space_and_dither(&cinfo, config, *this); -#endif + adjust_out_color_space_and_dither(&cinfo, colorType, *this); if (1 == sampleSize && SkImageDecoder::kDecodeBounds_Mode == mode) { // Assume an A8 bitmap is not opaque to avoid the check of each // individual pixel. It is very unlikely to be opaque, since // an opaque A8 bitmap would not be very interesting. // Otherwise, a jpeg image is opaque. - return bm->setConfig(config, cinfo.image_width, cinfo.image_height, 0, - SkBitmap::kA8_Config == config ? - kPremul_SkAlphaType : kOpaque_SkAlphaType); + return bm->setInfo(SkImageInfo::Make(cinfo.image_width, cinfo.image_height, + colorType, alphaType)); } /* image_width and image_height are the original dimensions, available @@ -606,27 +605,28 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { // individual pixel. It is very unlikely to be opaque, since // an opaque A8 bitmap would not be very interesting. // Otherwise, a jpeg image is opaque. - return bm->setConfig(config, smpl.scaledWidth(), smpl.scaledHeight(), - 0, SkBitmap::kA8_Config == config ? - kPremul_SkAlphaType : kOpaque_SkAlphaType); + return bm->setInfo(SkImageInfo::Make(smpl.scaledWidth(), smpl.scaledHeight(), + colorType, alphaType)); } else { return return_false(cinfo, *bm, "start_decompress"); } } sampleSize = recompute_sampleSize(sampleSize, cinfo); - // should we allow the Chooser (if present) to pick a config for us??? - if (!this->chooseFromOneChoice(config, cinfo.output_width, cinfo.output_height)) { +#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER + // should we allow the Chooser (if present) to pick a colortype for us??? + if (!this->chooseFromOneChoice(colorType, cinfo.output_width, cinfo.output_height)) { return return_false(cinfo, *bm, "chooseFromOneChoice"); } +#endif SkScaledBitmapSampler sampler(cinfo.output_width, cinfo.output_height, sampleSize); // Assume an A8 bitmap is not opaque to avoid the check of each // individual pixel. It is very unlikely to be opaque, since // an opaque A8 bitmap would not be very interesting. // Otherwise, a jpeg image is opaque. - bm->setConfig(config, sampler.scaledWidth(), sampler.scaledHeight(), 0, - SkBitmap::kA8_Config != config ? kOpaque_SkAlphaType : kPremul_SkAlphaType); + bm->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(), + colorType, alphaType)); if (SkImageDecoder::kDecodeBounds_Mode == mode) { return true; } @@ -641,10 +641,8 @@ bool SkJPEGImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { a significant performance boost. */ if (sampleSize == 1 && - ((config == SkBitmap::kARGB_8888_Config && - cinfo.out_color_space == JCS_RGBA_8888) || - (config == SkBitmap::kRGB_565_Config && - cinfo.out_color_space == JCS_RGB_565))) + ((kN32_SkColorType == colorType && cinfo.out_color_space == JCS_RGBA_8888) || + (kRGB_565_SkColorType == colorType && cinfo.out_color_space == JCS_RGB_565))) { JSAMPLE* rowptr = (JSAMPLE*)bm->getPixels(); INT32 const bpr = bm->rowBytes(); @@ -764,7 +762,7 @@ bool SkJPEGImageDecoder::onBuildTileIndex(SkStreamRewindable* stream, int *width // based on the config in onDecodeSubset. This should be fine, since // jpeg_init_read_tile_scanline will check out_color_space again after // that change (when it calls jinit_color_deconverter). - (void) this->getBitmapConfig(cinfo); + (void) this->getBitmapColorType(cinfo); turn_off_visual_optimizations(cinfo); @@ -815,10 +813,8 @@ bool SkJPEGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) { set_dct_method(*this, cinfo); - const SkBitmap::Config config = this->getBitmapConfig(cinfo); -#ifdef ANDROID_RGB - adjust_out_color_space_and_dither(cinfo, config, *this); -#endif + const SkColorType colorType = this->getBitmapColorType(cinfo); + adjust_out_color_space_and_dither(cinfo, colorType, *this); int startX = rect.fLeft; int startY = rect.fTop; @@ -833,14 +829,13 @@ bool SkJPEGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) { SkScaledBitmapSampler sampler(width, height, skiaSampleSize); SkBitmap bitmap; - bitmap.setConfig(config, sampler.scaledWidth(), sampler.scaledHeight()); // Assume an A8 bitmap is not opaque to avoid the check of each // individual pixel. It is very unlikely to be opaque, since // an opaque A8 bitmap would not be very interesting. // Otherwise, a jpeg image is opaque. - bitmap.setConfig(config, sampler.scaledWidth(), sampler.scaledHeight(), 0, - config == SkBitmap::kA8_Config ? kPremul_SkAlphaType : - kOpaque_SkAlphaType); + bitmap.setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(), colorType, + kAlpha_8_SkColorType == colorType ? + kPremul_SkAlphaType : kOpaque_SkAlphaType)); // Check ahead of time if the swap(dest, src) is possible or not. // If yes, then we will stick to AllocPixelRef since it's cheaper with the @@ -869,10 +864,8 @@ bool SkJPEGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) { a significant performance boost. */ if (skiaSampleSize == 1 && - ((config == SkBitmap::kARGB_8888_Config && - cinfo->out_color_space == JCS_RGBA_8888) || - (config == SkBitmap::kRGB_565_Config && - cinfo->out_color_space == JCS_RGB_565))) + ((kN32_SkColorType == colorType && cinfo->out_color_space == JCS_RGBA_8888) || + (kRGB_565_SkColorType == colorType && cinfo->out_color_space == JCS_RGB_565))) { JSAMPLE* rowptr = (JSAMPLE*)bitmap.getPixels(); INT32 const bpr = bitmap.rowBytes(); @@ -1116,14 +1109,14 @@ static void Write_Index_YUV(uint8_t* SK_RESTRICT dst, } static WriteScanline ChooseWriter(const SkBitmap& bm) { - switch (bm.config()) { - case SkBitmap::kARGB_8888_Config: + switch (bm.colorType()) { + case kN32_SkColorType: return Write_32_YUV; - case SkBitmap::kRGB_565_Config: + case kRGB_565_SkColorType: return Write_16_YUV; - case SkBitmap::kARGB_4444_Config: + case kARGB_4444_SkColorType: return Write_4444_YUV; - case SkBitmap::kIndex8_Config: + case kIndex_8_SkColorType: return Write_Index_YUV; default: return NULL; diff --git a/chromium/third_party/skia/src/images/SkImageDecoder_libpng.cpp b/chromium/third_party/skia/src/images/SkImageDecoder_libpng.cpp index 02ba6af90a3..7ff15584c4f 100644 --- a/chromium/third_party/skia/src/images/SkImageDecoder_libpng.cpp +++ b/chromium/third_party/skia/src/images/SkImageDecoder_libpng.cpp @@ -1,4 +1,3 @@ - /* * Copyright 2006 The Android Open Source Project * @@ -6,7 +5,6 @@ * found in the LICENSE file. */ - #include "SkImageDecoder.h" #include "SkImageEncoder.h" #include "SkColor.h" @@ -59,7 +57,7 @@ public: : fStream(stream) , fPng_ptr(png_ptr) , fInfo_ptr(info_ptr) - , fConfig(SkBitmap::kNo_Config) { + , fColorType(kUnknown_SkColorType) { SkASSERT(stream != NULL); stream->ref(); } @@ -72,7 +70,7 @@ public: SkAutoTUnref<SkStreamRewindable> fStream; png_structp fPng_ptr; png_infop fInfo_ptr; - SkBitmap::Config fConfig; + SkColorType fColorType; }; class SkPNGImageDecoder : public SkImageDecoder { @@ -102,9 +100,8 @@ private: bool decodePalette(png_structp png_ptr, png_infop info_ptr, bool * SK_RESTRICT hasAlphap, bool *reallyHasAlphap, SkColorTable **colorTablep); - bool getBitmapConfig(png_structp png_ptr, png_infop info_ptr, - SkBitmap::Config *config, bool *hasAlpha, - SkPMColor *theTranspColor); + bool getBitmapColorType(png_structp, png_infop, SkColorType*, bool* hasAlpha, + SkPMColor* theTranspColor); typedef SkImageDecoder INHERITED; }; @@ -169,7 +166,7 @@ static bool pos_le(int value, int max) { } static bool substituteTranspColor(SkBitmap* bm, SkPMColor match) { - SkASSERT(bm->config() == SkBitmap::kARGB_8888_Config); + SkASSERT(bm->colorType() == kN32_SkColorType); bool reallyHasAlpha = false; @@ -186,13 +183,12 @@ static bool substituteTranspColor(SkBitmap* bm, SkPMColor match) { return reallyHasAlpha; } -static bool canUpscalePaletteToConfig(SkBitmap::Config dstConfig, - bool srcHasAlpha) { - switch (dstConfig) { - case SkBitmap::kARGB_8888_Config: - case SkBitmap::kARGB_4444_Config: +static bool canUpscalePaletteToConfig(SkColorType dstColorType, bool srcHasAlpha) { + switch (dstColorType) { + case kN32_SkColorType: + case kARGB_4444_SkColorType: return true; - case SkBitmap::kRGB_565_Config: + case kRGB_565_SkColorType: // only return true if the src is opaque (since 565 is opaque) return !srcHasAlpha; default: @@ -317,21 +313,24 @@ bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap, } png_uint_32 origWidth, origHeight; - int bitDepth, colorType, interlaceType; + int bitDepth, pngColorType, interlaceType; png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth, - &colorType, &interlaceType, int_p_NULL, int_p_NULL); + &pngColorType, &interlaceType, int_p_NULL, int_p_NULL); - SkBitmap::Config config; + SkColorType colorType; bool hasAlpha = false; SkPMColor theTranspColor = 0; // 0 tells us not to try to match - if (!this->getBitmapConfig(png_ptr, info_ptr, &config, &hasAlpha, &theTranspColor)) { + if (!this->getBitmapColorType(png_ptr, info_ptr, &colorType, &hasAlpha, &theTranspColor)) { return false; } + SkAlphaType alphaType = this->getRequireUnpremultipliedColors() ? + kUnpremul_SkAlphaType : kPremul_SkAlphaType; const int sampleSize = this->getSampleSize(); SkScaledBitmapSampler sampler(origWidth, origHeight, sampleSize); - decodedBitmap->setConfig(config, sampler.scaledWidth(), sampler.scaledHeight()); + decodedBitmap->setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(), + colorType, alphaType)); if (SkImageDecoder::kDecodeBounds_Mode == mode) { return true; @@ -345,14 +344,14 @@ bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap, bool reallyHasAlpha = false; SkColorTable* colorTable = NULL; - if (colorType == PNG_COLOR_TYPE_PALETTE) { + if (pngColorType == PNG_COLOR_TYPE_PALETTE) { decodePalette(png_ptr, info_ptr, &hasAlpha, &reallyHasAlpha, &colorTable); } SkAutoUnref aur(colorTable); if (!this->allocPixelRef(decodedBitmap, - SkBitmap::kIndex8_Config == config ? colorTable : NULL)) { + kIndex_8_SkColorType == colorType ? colorTable : NULL)) { return false; } @@ -371,15 +370,15 @@ bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap, */ png_read_update_info(png_ptr, info_ptr); - if ((SkBitmap::kA8_Config == config || SkBitmap::kIndex8_Config == config) - && 1 == sampleSize) { - if (SkBitmap::kA8_Config == config) { + if ((kAlpha_8_SkColorType == colorType || kIndex_8_SkColorType == colorType) && + 1 == sampleSize) { + if (kAlpha_8_SkColorType == colorType) { // For an A8 bitmap, we assume there is an alpha for speed. It is // possible the bitmap is opaque, but that is an unlikely use case // since it would not be very interesting. reallyHasAlpha = true; // A8 is only allowed if the original was GRAY. - SkASSERT(PNG_COLOR_TYPE_GRAY == colorType); + SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType); } for (int i = 0; i < number_passes; i++) { for (png_uint_32 y = 0; y < origHeight; y++) { @@ -394,9 +393,9 @@ bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap, if (colorTable != NULL) { sc = SkScaledBitmapSampler::kIndex; srcBytesPerPixel = 1; - } else if (SkBitmap::kA8_Config == config) { + } else if (kAlpha_8_SkColorType == colorType) { // A8 is only allowed if the original was GRAY. - SkASSERT(PNG_COLOR_TYPE_GRAY == colorType); + SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType); sc = SkScaledBitmapSampler::kGray; srcBytesPerPixel = 1; } else if (hasAlpha) { @@ -463,14 +462,14 @@ bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap, reallyHasAlpha |= substituteTranspColor(decodedBitmap, theTranspColor); } if (reallyHasAlpha && this->getRequireUnpremultipliedColors()) { - switch (decodedBitmap->config()) { - case SkBitmap::kIndex8_Config: + switch (decodedBitmap->colorType()) { + case kIndex_8_SkColorType: // Fall through. - case SkBitmap::kARGB_4444_Config: - // We have chosen not to support unpremul for these configs. + case kARGB_4444_SkColorType: + // We have chosen not to support unpremul for these colortypes. return false; default: { - // Fall through to finish the decode. This config either + // Fall through to finish the decode. This colortype either // supports unpremul or it is irrelevant because it has no // alpha (or only alpha). // These brackets prevent a warning. @@ -478,24 +477,18 @@ bool SkPNGImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap, } } - SkAlphaType alphaType = kOpaque_SkAlphaType; - if (reallyHasAlpha) { - if (this->getRequireUnpremultipliedColors()) { - alphaType = kUnpremul_SkAlphaType; - } else { - alphaType = kPremul_SkAlphaType; - } + if (!reallyHasAlpha) { + decodedBitmap->setAlphaType(kOpaque_SkAlphaType); } - decodedBitmap->setAlphaType(alphaType); return true; } -bool SkPNGImageDecoder::getBitmapConfig(png_structp png_ptr, png_infop info_ptr, - SkBitmap::Config* SK_RESTRICT configp, - bool* SK_RESTRICT hasAlphap, - SkPMColor* SK_RESTRICT theTranspColorp) { +bool SkPNGImageDecoder::getBitmapColorType(png_structp png_ptr, png_infop info_ptr, + SkColorType* colorTypep, + bool* hasAlphap, + SkPMColor* SK_RESTRICT theTranspColorp) { png_uint_32 origWidth, origHeight; int bitDepth, colorType; png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth, @@ -519,10 +512,10 @@ bool SkPNGImageDecoder::getBitmapConfig(png_structp png_ptr, png_infop info_ptr, if (colorType == PNG_COLOR_TYPE_PALETTE) { bool paletteHasAlpha = hasTransparencyInPalette(png_ptr, info_ptr); - *configp = this->getPrefConfig(kIndex_SrcDepth, paletteHasAlpha); - // now see if we can upscale to their requested config - if (!canUpscalePaletteToConfig(*configp, paletteHasAlpha)) { - *configp = SkBitmap::kIndex8_Config; + *colorTypep = this->getPrefColorType(kIndex_SrcDepth, paletteHasAlpha); + // now see if we can upscale to their requested colortype + if (!canUpscalePaletteToConfig(*colorTypep, paletteHasAlpha)) { + *colorTypep = kIndex_8_SkColorType; } } else { png_color_16p transpColor = NULL; @@ -586,62 +579,59 @@ bool SkPNGImageDecoder::getBitmapConfig(png_structp png_ptr, png_infop info_ptr, //SkASSERT(!*hasAlphap); } - *configp = this->getPrefConfig(srcDepth, *hasAlphap); + *colorTypep = this->getPrefColorType(srcDepth, *hasAlphap); // now match the request against our capabilities if (*hasAlphap) { - if (*configp != SkBitmap::kARGB_4444_Config) { - *configp = SkBitmap::kARGB_8888_Config; + if (*colorTypep != kARGB_4444_SkColorType) { + *colorTypep = kN32_SkColorType; } } else { - if (SkBitmap::kA8_Config == *configp) { + if (kAlpha_8_SkColorType == *colorTypep) { if (k8BitGray_SrcDepth != srcDepth) { // Converting a non grayscale image to A8 is not currently supported. - *configp = SkBitmap::kARGB_8888_Config; + *colorTypep = kN32_SkColorType; } - } else if (*configp != SkBitmap::kRGB_565_Config && - *configp != SkBitmap::kARGB_4444_Config) { - *configp = SkBitmap::kARGB_8888_Config; + } else if (*colorTypep != kRGB_565_SkColorType && + *colorTypep != kARGB_4444_SkColorType) { + *colorTypep = kN32_SkColorType; } } } // sanity check for size { - Sk64 size; - size.setMul(origWidth, origHeight); - if (size.isNeg() || !size.is32()) { - return false; - } + int64_t size = sk_64_mul(origWidth, origHeight); // now check that if we are 4-bytes per pixel, we also don't overflow - if (size.get32() > (0x7FFFFFFF >> 2)) { + if (size < 0 || size > (0x7FFFFFFF >> 2)) { return false; } } - if (!this->chooseFromOneChoice(*configp, origWidth, origHeight)) { +#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER + if (!this->chooseFromOneChoice(*colorTypep, origWidth, origHeight)) { return false; } +#endif // If the image has alpha and the decoder wants unpremultiplied - // colors, the only supported config is 8888. + // colors, the only supported colortype is 8888. if (this->getRequireUnpremultipliedColors() && *hasAlphap) { - *configp = SkBitmap::kARGB_8888_Config; + *colorTypep = kN32_SkColorType; } if (fImageIndex != NULL) { - if (SkBitmap::kNo_Config == fImageIndex->fConfig) { + if (kUnknown_SkColorType == fImageIndex->fColorType) { // This is the first time for this subset decode. From now on, - // all decodes must be in the same config. - fImageIndex->fConfig = *configp; - } else if (fImageIndex->fConfig != *configp) { - // Requesting a different config for a subsequent decode is not + // all decodes must be in the same colortype. + fImageIndex->fColorType = *colorTypep; + } else if (fImageIndex->fColorType != *colorTypep) { + // Requesting a different colortype for a subsequent decode is not // supported. Report failure before we make changes to png_ptr. return false; } } - bool convertGrayToRGB = PNG_COLOR_TYPE_GRAY == colorType - && *configp != SkBitmap::kA8_Config; + bool convertGrayToRGB = PNG_COLOR_TYPE_GRAY == colorType && *colorTypep != kAlpha_8_SkColorType; // Unless the user is requesting A8, convert a grayscale image into RGB. // GRAY_ALPHA will always be converted to RGB @@ -695,7 +685,7 @@ bool SkPNGImageDecoder::decodePalette(png_structp png_ptr, png_infop info_ptr, int transLessThanFF = 0; // Choose which function to use to create the color table. If the final destination's - // config is unpremultiplied, the color table will store unpremultiplied colors. + // colortype is unpremultiplied, the color table will store unpremultiplied colors. PackColorProc proc; if (this->getRequireUnpremultipliedColors()) { proc = &SkPackARGB32NoCheck; @@ -779,9 +769,9 @@ bool SkPNGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) { } png_uint_32 origWidth, origHeight; - int bitDepth, colorType, interlaceType; + int bitDepth, pngColorType, interlaceType; png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bitDepth, - &colorType, &interlaceType, int_p_NULL, int_p_NULL); + &pngColorType, &interlaceType, int_p_NULL, int_p_NULL); SkIRect rect = SkIRect::MakeWH(origWidth, origHeight); @@ -791,11 +781,11 @@ bool SkPNGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) { return false; } - SkBitmap::Config config; + SkColorType colorType; bool hasAlpha = false; SkPMColor theTranspColor = 0; // 0 tells us not to try to match - if (!this->getBitmapConfig(png_ptr, info_ptr, &config, &hasAlpha, &theTranspColor)) { + if (!this->getBitmapColorType(png_ptr, info_ptr, &colorType, &hasAlpha, &theTranspColor)) { return false; } @@ -803,7 +793,8 @@ bool SkPNGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) { SkScaledBitmapSampler sampler(origWidth, rect.height(), sampleSize); SkBitmap decodedBitmap; - decodedBitmap.setConfig(config, sampler.scaledWidth(), sampler.scaledHeight()); + decodedBitmap.setInfo(SkImageInfo::Make(sampler.scaledWidth(), sampler.scaledHeight(), + colorType, kPremul_SkAlphaType)); // from here down we are concerned with colortables and pixels @@ -813,7 +804,7 @@ bool SkPNGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) { bool reallyHasAlpha = false; SkColorTable* colorTable = NULL; - if (colorType == PNG_COLOR_TYPE_PALETTE) { + if (pngColorType == PNG_COLOR_TYPE_PALETTE) { decodePalette(png_ptr, info_ptr, &hasAlpha, &reallyHasAlpha, &colorTable); } @@ -826,7 +817,7 @@ bool SkPNGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) { int h = rect.height() / sampleSize; const bool swapOnly = (rect == region) && (w == decodedBitmap.width()) && (h == decodedBitmap.height()) && bm->isNull(); - const bool needColorTable = SkBitmap::kIndex8_Config == config; + const bool needColorTable = kIndex_8_SkColorType == colorType; if (swapOnly) { if (!this->allocPixelRef(&decodedBitmap, needColorTable ? colorTable : NULL)) { return false; @@ -861,15 +852,15 @@ bool SkPNGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) { int actualTop = rect.fTop; - if ((SkBitmap::kA8_Config == config || SkBitmap::kIndex8_Config == config) + if ((kAlpha_8_SkColorType == colorType || kIndex_8_SkColorType == colorType) && 1 == sampleSize) { - if (SkBitmap::kA8_Config == config) { + if (kAlpha_8_SkColorType == colorType) { // For an A8 bitmap, we assume there is an alpha for speed. It is // possible the bitmap is opaque, but that is an unlikely use case // since it would not be very interesting. reallyHasAlpha = true; // A8 is only allowed if the original was GRAY. - SkASSERT(PNG_COLOR_TYPE_GRAY == colorType); + SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType); } for (int i = 0; i < number_passes; i++) { @@ -891,9 +882,9 @@ bool SkPNGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) { if (colorTable != NULL) { sc = SkScaledBitmapSampler::kIndex; srcBytesPerPixel = 1; - } else if (SkBitmap::kA8_Config == config) { + } else if (kAlpha_8_SkColorType == colorType) { // A8 is only allowed if the original was GRAY. - SkASSERT(PNG_COLOR_TYPE_GRAY == colorType); + SkASSERT(PNG_COLOR_TYPE_GRAY == pngColorType); sc = SkScaledBitmapSampler::kGray; srcBytesPerPixel = 1; } else if (hasAlpha) { @@ -962,11 +953,11 @@ bool SkPNGImageDecoder::onDecodeSubset(SkBitmap* bm, const SkIRect& region) { reallyHasAlpha |= substituteTranspColor(&decodedBitmap, theTranspColor); } if (reallyHasAlpha && this->getRequireUnpremultipliedColors()) { - switch (decodedBitmap.config()) { - case SkBitmap::kIndex8_Config: + switch (decodedBitmap.colorType()) { + case kIndex_8_SkColorType: // Fall through. - case SkBitmap::kARGB_4444_Config: - // We have chosen not to support unpremul for these configs. + case kARGB_4444_SkColorType: + // We have chosen not to support unpremul for these colortypess. return false; default: { // Fall through to finish the decode. This config either @@ -1007,29 +998,28 @@ static void sk_write_fn(png_structp png_ptr, png_bytep data, png_size_t len) { } } -static transform_scanline_proc choose_proc(SkBitmap::Config config, - bool hasAlpha) { +static transform_scanline_proc choose_proc(SkColorType ct, bool hasAlpha) { // we don't care about search on alpha if we're kIndex8, since only the // colortable packing cares about that distinction, not the pixels - if (SkBitmap::kIndex8_Config == config) { + if (kIndex_8_SkColorType == ct) { hasAlpha = false; // we store false in the table entries for kIndex8 } static const struct { - SkBitmap::Config fConfig; + SkColorType fColorType; bool fHasAlpha; transform_scanline_proc fProc; } gMap[] = { - { SkBitmap::kRGB_565_Config, false, transform_scanline_565 }, - { SkBitmap::kARGB_8888_Config, false, transform_scanline_888 }, - { SkBitmap::kARGB_8888_Config, true, transform_scanline_8888 }, - { SkBitmap::kARGB_4444_Config, false, transform_scanline_444 }, - { SkBitmap::kARGB_4444_Config, true, transform_scanline_4444 }, - { SkBitmap::kIndex8_Config, false, transform_scanline_memcpy }, + { kRGB_565_SkColorType, false, transform_scanline_565 }, + { kN32_SkColorType, false, transform_scanline_888 }, + { kN32_SkColorType, true, transform_scanline_8888 }, + { kARGB_4444_SkColorType, false, transform_scanline_444 }, + { kARGB_4444_SkColorType, true, transform_scanline_4444 }, + { kIndex_8_SkColorType, false, transform_scanline_memcpy }, }; for (int i = SK_ARRAY_COUNT(gMap) - 1; i >= 0; --i) { - if (gMap[i].fConfig == config && gMap[i].fHasAlpha == hasAlpha) { + if (gMap[i].fColorType == ct && gMap[i].fHasAlpha == hasAlpha) { return gMap[i].fProc; } } @@ -1116,38 +1106,37 @@ protected: private: bool doEncode(SkWStream* stream, const SkBitmap& bm, const bool& hasAlpha, int colorType, - int bitDepth, SkBitmap::Config config, + int bitDepth, SkColorType ct, png_color_8& sig_bit); typedef SkImageEncoder INHERITED; }; -bool SkPNGImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bitmap, - int /*quality*/) { - SkBitmap::Config config = bitmap.config(); +bool SkPNGImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bitmap, int /*quality*/) { + SkColorType ct = bitmap.colorType(); const bool hasAlpha = !bitmap.isOpaque(); int colorType = PNG_COLOR_MASK_COLOR; int bitDepth = 8; // default for color png_color_8 sig_bit; - switch (config) { - case SkBitmap::kIndex8_Config: + switch (ct) { + case kIndex_8_SkColorType: colorType |= PNG_COLOR_MASK_PALETTE; // fall through to the ARGB_8888 case - case SkBitmap::kARGB_8888_Config: + case kN32_SkColorType: sig_bit.red = 8; sig_bit.green = 8; sig_bit.blue = 8; sig_bit.alpha = 8; break; - case SkBitmap::kARGB_4444_Config: + case kARGB_4444_SkColorType: sig_bit.red = 4; sig_bit.green = 4; sig_bit.blue = 4; sig_bit.alpha = 4; break; - case SkBitmap::kRGB_565_Config: + case kRGB_565_SkColorType: sig_bit.red = 5; sig_bit.green = 6; sig_bit.blue = 5; @@ -1182,13 +1171,12 @@ bool SkPNGImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bitmap, bitDepth = computeBitDepth(ctable->count()); } - return doEncode(stream, bitmap, hasAlpha, colorType, - bitDepth, config, sig_bit); + return doEncode(stream, bitmap, hasAlpha, colorType, bitDepth, ct, sig_bit); } bool SkPNGImageEncoder::doEncode(SkWStream* stream, const SkBitmap& bitmap, const bool& hasAlpha, int colorType, - int bitDepth, SkBitmap::Config config, + int bitDepth, SkColorType ct, png_color_8& sig_bit) { png_structp png_ptr; @@ -1233,7 +1221,7 @@ bool SkPNGImageEncoder::doEncode(SkWStream* stream, const SkBitmap& bitmap, // set our colortable/trans arrays if needed png_color paletteColors[256]; png_byte trans[256]; - if (SkBitmap::kIndex8_Config == config) { + if (kIndex_8_SkColorType == ct) { SkColorTable* ct = bitmap.getColorTable(); int numTrans = pack_palette(ct, paletteColors, trans, hasAlpha); png_set_PLTE(png_ptr, info_ptr, paletteColors, ct->count()); @@ -1248,7 +1236,7 @@ bool SkPNGImageEncoder::doEncode(SkWStream* stream, const SkBitmap& bitmap, const char* srcImage = (const char*)bitmap.getPixels(); SkAutoSMalloc<1024> rowStorage(bitmap.width() << 2); char* storage = (char*)rowStorage.get(); - transform_scanline_proc proc = choose_proc(config, hasAlpha); + transform_scanline_proc proc = choose_proc(ct, hasAlpha); for (int y = 0; y < bitmap.height(); y++) { png_bytep row_ptr = (png_bytep)storage; diff --git a/chromium/third_party/skia/src/images/SkImageDecoder_libwebp.cpp b/chromium/third_party/skia/src/images/SkImageDecoder_libwebp.cpp index ab58aef135b..f7cfa8b4cca 100644 --- a/chromium/third_party/skia/src/images/SkImageDecoder_libwebp.cpp +++ b/chromium/third_party/skia/src/images/SkImageDecoder_libwebp.cpp @@ -80,13 +80,12 @@ static bool webp_parse_header(SkStream* stream, int* width, int* height, int* al // sanity check for image size that's about to be decoded. { - Sk64 size; - size.setMul(*width, *height); - if (size.isNeg() || !size.is32()) { + int64_t size = sk_64_mul(*width, *height); + if (!sk_64_isS32(size)) { return false; } // now check that if we are 4-bytes per pixel, we also don't overflow - if (size.get32() > (0x7FFFFFFF >> 2)) { + if (sk_64_asS32(size) > (0x7FFFFFFF >> 2)) { return false; } } @@ -170,13 +169,19 @@ static bool return_false(const SkBitmap& bm, const char msg[]) { static WEBP_CSP_MODE webp_decode_mode(const SkBitmap* decodedBitmap, bool premultiply) { WEBP_CSP_MODE mode = MODE_LAST; - SkBitmap::Config config = decodedBitmap->config(); - - if (config == SkBitmap::kARGB_8888_Config) { - mode = premultiply ? MODE_rgbA : MODE_RGBA; - } else if (config == SkBitmap::kARGB_4444_Config) { + const SkColorType ct = decodedBitmap->colorType(); + + if (ct == kN32_SkColorType) { + #if SK_PMCOLOR_BYTE_ORDER(B,G,R,A) + mode = premultiply ? MODE_bgrA : MODE_BGRA; + #elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A) + mode = premultiply ? MODE_rgbA : MODE_RGBA; + #else + #error "Skia uses BGRA or RGBA byte order" + #endif + } else if (ct == kARGB_4444_SkColorType) { mode = premultiply ? MODE_rgbA_4444 : MODE_RGBA_4444; - } else if (config == SkBitmap::kRGB_565_Config) { + } else if (ct == kRGB_565_SkColorType) { mode = MODE_RGB_565; } SkASSERT(MODE_LAST != mode); @@ -273,28 +278,35 @@ static bool webp_get_config_resize_crop(WebPDecoderConfig* config, return true; } -bool SkWEBPImageDecoder::setDecodeConfig(SkBitmap* decodedBitmap, - int width, int height) { - SkBitmap::Config config = this->getPrefConfig(k32Bit_SrcDepth, SkToBool(fHasAlpha)); +bool SkWEBPImageDecoder::setDecodeConfig(SkBitmap* decodedBitmap, int width, int height) { + SkColorType colorType = this->getPrefColorType(k32Bit_SrcDepth, SkToBool(fHasAlpha)); // YUV converter supports output in RGB565, RGBA4444 and RGBA8888 formats. if (fHasAlpha) { - if (config != SkBitmap::kARGB_4444_Config) { - config = SkBitmap::kARGB_8888_Config; + if (colorType != kARGB_4444_SkColorType) { + colorType = kN32_SkColorType; } } else { - if (config != SkBitmap::kRGB_565_Config && - config != SkBitmap::kARGB_4444_Config) { - config = SkBitmap::kARGB_8888_Config; + if (colorType != kRGB_565_SkColorType && colorType != kARGB_4444_SkColorType) { + colorType = kN32_SkColorType; } } - if (!this->chooseFromOneChoice(config, width, height)) { +#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER + if (!this->chooseFromOneChoice(colorType, width, height)) { return false; } +#endif - return decodedBitmap->setConfig(config, width, height, 0, - fHasAlpha ? kPremul_SkAlphaType : kOpaque_SkAlphaType); + SkAlphaType alphaType = kOpaque_SkAlphaType; + if (SkToBool(fHasAlpha)) { + if (this->getRequireUnpremultipliedColors()) { + alphaType = kUnpremul_SkAlphaType; + } else { + alphaType = kPremul_SkAlphaType; + } + } + return decodedBitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType)); } bool SkWEBPImageDecoder::onBuildTileIndex(SkStreamRewindable* stream, @@ -321,10 +333,8 @@ bool SkWEBPImageDecoder::onBuildTileIndex(SkStreamRewindable* stream, } static bool is_config_compatible(const SkBitmap& bitmap) { - SkBitmap::Config config = bitmap.config(); - return config == SkBitmap::kARGB_4444_Config || - config == SkBitmap::kRGB_565_Config || - config == SkBitmap::kARGB_8888_Config; + const SkColorType ct = bitmap.colorType(); + return ct == kARGB_4444_SkColorType || ct == kRGB_565_SkColorType || ct == kN32_SkColorType; } bool SkWEBPImageDecoder::onDecodeSubset(SkBitmap* decodedBitmap, @@ -369,12 +379,14 @@ bool SkWEBPImageDecoder::onDecodeSubset(SkBitmap* decodedBitmap, if (!allocResult) { return return_false(*decodedBitmap, "allocPixelRef"); } +#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER } else { // This is also called in setDecodeConfig in above block. // i.e., when bitmap->isNull() is true. - if (!chooseFromOneChoice(bitmap->config(), width, height)) { + if (!chooseFromOneChoice(bitmap->colorType(), width, height)) { return false; } +#endif } SkAutoLockPixels alp(*bitmap); @@ -439,6 +451,8 @@ bool SkWEBPImageDecoder::onDecode(SkStream* stream, SkBitmap* decodedBitmap, /////////////////////////////////////////////////////////////////////////////// +#include "SkUnPreMultiply.h" + typedef void (*ScanlineImporter)(const uint8_t* in, uint8_t* out, int width, const SkPMColor* SK_RESTRICT ctable); @@ -454,6 +468,31 @@ static void ARGB_8888_To_RGB(const uint8_t* in, uint8_t* rgb, int width, } } +static void ARGB_8888_To_RGBA(const uint8_t* in, uint8_t* rgb, int width, + const SkPMColor*) { + const uint32_t* SK_RESTRICT src = (const uint32_t*)in; + const SkUnPreMultiply::Scale* SK_RESTRICT table = + SkUnPreMultiply::GetScaleTable(); + for (int i = 0; i < width; ++i) { + const uint32_t c = *src++; + uint8_t a = SkGetPackedA32(c); + uint8_t r = SkGetPackedR32(c); + uint8_t g = SkGetPackedG32(c); + uint8_t b = SkGetPackedB32(c); + if (0 != a && 255 != a) { + SkUnPreMultiply::Scale scale = table[a]; + r = SkUnPreMultiply::ApplyScale(scale, r); + g = SkUnPreMultiply::ApplyScale(scale, g); + b = SkUnPreMultiply::ApplyScale(scale, b); + } + rgb[0] = r; + rgb[1] = g; + rgb[2] = b; + rgb[3] = a; + rgb += 4; + } +} + static void RGB_565_To_RGB(const uint8_t* in, uint8_t* rgb, int width, const SkPMColor*) { const uint16_t* SK_RESTRICT src = (const uint16_t*)in; @@ -478,6 +517,31 @@ static void ARGB_4444_To_RGB(const uint8_t* in, uint8_t* rgb, int width, } } +static void ARGB_4444_To_RGBA(const uint8_t* in, uint8_t* rgb, int width, + const SkPMColor*) { + const SkPMColor16* SK_RESTRICT src = (const SkPMColor16*)in; + const SkUnPreMultiply::Scale* SK_RESTRICT table = + SkUnPreMultiply::GetScaleTable(); + for (int i = 0; i < width; ++i) { + const SkPMColor16 c = *src++; + uint8_t a = SkPacked4444ToA32(c); + uint8_t r = SkPacked4444ToR32(c); + uint8_t g = SkPacked4444ToG32(c); + uint8_t b = SkPacked4444ToB32(c); + if (0 != a && 255 != a) { + SkUnPreMultiply::Scale scale = table[a]; + r = SkUnPreMultiply::ApplyScale(scale, r); + g = SkUnPreMultiply::ApplyScale(scale, g); + b = SkUnPreMultiply::ApplyScale(scale, b); + } + rgb[0] = r; + rgb[1] = g; + rgb[2] = b; + rgb[3] = a; + rgb += 4; + } +} + static void Index8_To_RGB(const uint8_t* in, uint8_t* rgb, int width, const SkPMColor* SK_RESTRICT ctable) { const uint8_t* SK_RESTRICT src = (const uint8_t*)in; @@ -490,15 +554,29 @@ static void Index8_To_RGB(const uint8_t* in, uint8_t* rgb, int width, } } -static ScanlineImporter ChooseImporter(const SkBitmap::Config& config) { - switch (config) { - case SkBitmap::kARGB_8888_Config: - return ARGB_8888_To_RGB; - case SkBitmap::kRGB_565_Config: +static ScanlineImporter ChooseImporter(SkColorType ct, bool hasAlpha, int* bpp) { + switch (ct) { + case kN32_SkColorType: + if (hasAlpha) { + *bpp = 4; + return ARGB_8888_To_RGBA; + } else { + *bpp = 3; + return ARGB_8888_To_RGB; + } + case kARGB_4444_SkColorType: + if (hasAlpha) { + *bpp = 4; + return ARGB_4444_To_RGBA; + } else { + *bpp = 3; + return ARGB_4444_To_RGB; + } + case kRGB_565_SkColorType: + *bpp = 3; return RGB_565_To_RGB; - case SkBitmap::kARGB_4444_Config: - return ARGB_4444_To_RGB; - case SkBitmap::kIndex8_Config: + case kIndex_8_SkColorType: + *bpp = 3; return Index8_To_RGB; default: return NULL; @@ -521,11 +599,15 @@ private: bool SkWEBPImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bm, int quality) { - const SkBitmap::Config config = bm.config(); - const ScanlineImporter scanline_import = ChooseImporter(config); + const bool hasAlpha = !bm.isOpaque(); + int bpp = -1; + const ScanlineImporter scanline_import = ChooseImporter(bm.colorType(), hasAlpha, &bpp); if (NULL == scanline_import) { return false; } + if (-1 == bpp) { + return false; + } SkAutoLockPixels alp(bm); SkAutoLockColors ctLocker; @@ -547,7 +629,7 @@ bool SkWEBPImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bm, const SkPMColor* colors = ctLocker.lockColors(bm); const uint8_t* src = (uint8_t*)bm.getPixels(); - const int rgbStride = pic.width * 3; + const int rgbStride = pic.width * bpp; // Import (for each scanline) the bit-map image (in appropriate color-space) // to RGB color space. @@ -557,7 +639,12 @@ bool SkWEBPImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bm, pic.width, colors); } - bool ok = SkToBool(WebPPictureImportRGB(&pic, rgb, rgbStride)); + bool ok; + if (bpp == 3) { + ok = SkToBool(WebPPictureImportRGB(&pic, rgb, rgbStride)); + } else { + ok = SkToBool(WebPPictureImportRGBA(&pic, rgb, rgbStride)); + } delete[] rgb; ok = ok && WebPEncode(&webp_config, &pic); diff --git a/chromium/third_party/skia/src/images/SkImageDecoder_pkm.cpp b/chromium/third_party/skia/src/images/SkImageDecoder_pkm.cpp new file mode 100644 index 00000000000..d555c6afccc --- /dev/null +++ b/chromium/third_party/skia/src/images/SkImageDecoder_pkm.cpp @@ -0,0 +1,133 @@ +/* + * 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 "SkColorPriv.h" +#include "SkImageDecoder.h" +#include "SkScaledBitmapSampler.h" +#include "SkStream.h" +#include "SkStreamHelpers.h" +#include "SkTypes.h" + +#include "etc1.h" + +class SkPKMImageDecoder : public SkImageDecoder { +public: + SkPKMImageDecoder() { } + + virtual Format getFormat() const SK_OVERRIDE { + return kPKM_Format; + } + +protected: + virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; + +private: + typedef SkImageDecoder INHERITED; +}; + +///////////////////////////////////////////////////////////////////////////////////////// + +bool SkPKMImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { + SkAutoMalloc autoMal; + const size_t length = CopyStreamToStorage(&autoMal, stream); + if (0 == length) { + return false; + } + + unsigned char* buf = (unsigned char*)autoMal.get(); + + // Make sure original PKM header is there... + SkASSERT(etc1_pkm_is_valid(buf)); + + const unsigned short width = etc1_pkm_get_width(buf); + const unsigned short height = etc1_pkm_get_height(buf); + +#ifdef SK_SUPPORT_LEGACY_IMAGEDECODER_CHOOSER + // should we allow the Chooser (if present) to pick a config for us??? + if (!this->chooseFromOneChoice(kN32_SkColorType, width, height)) { + return false; + } +#endif + + // Setup the sampler... + SkScaledBitmapSampler sampler(width, height, this->getSampleSize()); + + // Set the config... + bm->setInfo(SkImageInfo::MakeN32(sampler.scaledWidth(), sampler.scaledHeight(), + kOpaque_SkAlphaType)); + if (SkImageDecoder::kDecodeBounds_Mode == mode) { + return true; + } + + if (!this->allocPixelRef(bm, NULL)) { + return false; + } + + // Lock the pixels, since we're about to write to them... + SkAutoLockPixels alp(*bm); + + if (!sampler.begin(bm, SkScaledBitmapSampler::kRGB, *this)) { + return false; + } + + // Advance buffer past the header + buf += ETC_PKM_HEADER_SIZE; + + // ETC1 Data is encoded as RGB pixels, so we should extract it as such + int nPixels = width * height; + SkAutoMalloc outRGBData(nPixels * 3); + etc1_byte *outRGBDataPtr = reinterpret_cast<etc1_byte *>(outRGBData.get()); + + // Decode ETC1 + if (etc1_decode_image(buf, outRGBDataPtr, width, height, 3, width*3)) { + return false; + } + + // Set each of the pixels... + const int srcRowBytes = width * 3; + const int dstHeight = sampler.scaledHeight(); + const uint8_t *srcRow = reinterpret_cast<uint8_t *>(outRGBDataPtr); + srcRow += sampler.srcY0() * srcRowBytes; + for (int y = 0; y < dstHeight; ++y) { + sampler.next(srcRow); + srcRow += sampler.srcDY() * srcRowBytes; + } + + return true; +} + +///////////////////////////////////////////////////////////////////////////////////////// +DEFINE_DECODER_CREATOR(PKMImageDecoder); +///////////////////////////////////////////////////////////////////////////////////////// + +static bool is_pkm(SkStreamRewindable* stream) { + // Read the PKM header and make sure it's valid. + unsigned char buf[ETC_PKM_HEADER_SIZE]; + if (stream->read((void*)buf, ETC_PKM_HEADER_SIZE) != ETC_PKM_HEADER_SIZE) { + return false; + } + + return SkToBool(etc1_pkm_is_valid(buf)); +} + +static SkImageDecoder* sk_libpkm_dfactory(SkStreamRewindable* stream) { + if (is_pkm(stream)) { + return SkNEW(SkPKMImageDecoder); + } + return NULL; +} + +static SkImageDecoder_DecodeReg gReg(sk_libpkm_dfactory); + +static SkImageDecoder::Format get_format_pkm(SkStreamRewindable* stream) { + if (is_pkm(stream)) { + return SkImageDecoder::kPKM_Format; + } + return SkImageDecoder::kUnknown_Format; +} + +static SkImageDecoder_FormatReg gFormatReg(get_format_pkm); diff --git a/chromium/third_party/skia/src/images/SkImageDecoder_wbmp.cpp b/chromium/third_party/skia/src/images/SkImageDecoder_wbmp.cpp index 8dce62cdf00..0bf138940da 100644 --- a/chromium/third_party/skia/src/images/SkImageDecoder_wbmp.cpp +++ b/chromium/third_party/skia/src/images/SkImageDecoder_wbmp.cpp @@ -111,8 +111,8 @@ bool SkWBMPImageDecoder::onDecode(SkStream* stream, SkBitmap* decodedBitmap, int width = head.fWidth; int height = head.fHeight; - decodedBitmap->setConfig(SkBitmap::kIndex8_Config, width, height, 0, - kOpaque_SkAlphaType); + decodedBitmap->setInfo(SkImageInfo::Make(width, height, + kIndex_8_SkColorType, kOpaque_SkAlphaType)); if (SkImageDecoder::kDecodeBounds_Mode == mode) { return true; diff --git a/chromium/third_party/skia/src/images/SkImageEncoder_argb.cpp b/chromium/third_party/skia/src/images/SkImageEncoder_argb.cpp index 97b741b8bf1..296491eef81 100644 --- a/chromium/third_party/skia/src/images/SkImageEncoder_argb.cpp +++ b/chromium/third_party/skia/src/images/SkImageEncoder_argb.cpp @@ -71,15 +71,15 @@ static void Index8_To_ARGB(const uint8_t* in, uint8_t* argb, int width, } } -static ScanlineImporter ChooseImporter(const SkBitmap::Config& config) { - switch (config) { - case SkBitmap::kARGB_8888_Config: +static ScanlineImporter ChooseImporter(SkColorType ct) { + switch (ct) { + case kN32_SkColorType: return ARGB_8888_To_ARGB; - case SkBitmap::kRGB_565_Config: + case kRGB_565_SkColorType: return RGB_565_To_ARGB; - case SkBitmap::kARGB_4444_Config: + case kARGB_4444_SkColorType: return ARGB_4444_To_ARGB; - case SkBitmap::kIndex8_Config: + case kIndex_8_SkColorType: return Index8_To_ARGB; default: return NULL; @@ -87,8 +87,7 @@ static ScanlineImporter ChooseImporter(const SkBitmap::Config& config) { } bool SkARGBImageEncoder::onEncode(SkWStream* stream, const SkBitmap& bitmap, int) { - const SkBitmap::Config config = bitmap.config(); - const ScanlineImporter scanline_import = ChooseImporter(config); + const ScanlineImporter scanline_import = ChooseImporter(bitmap.colorType()); if (NULL == scanline_import) { return false; } diff --git a/chromium/third_party/skia/src/images/SkImageRef.cpp b/chromium/third_party/skia/src/images/SkImageRef.cpp deleted file mode 100644 index 716519f080d..00000000000 --- a/chromium/third_party/skia/src/images/SkImageRef.cpp +++ /dev/null @@ -1,191 +0,0 @@ - -/* - * Copyright 2011 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -#include "SkImageRef.h" -#include "SkBitmap.h" -#include "SkFlattenableBuffers.h" -#include "SkImageDecoder.h" -#include "SkStream.h" -#include "SkTemplates.h" -#include "SkThread.h" - -//#define DUMP_IMAGEREF_LIFECYCLE - - -/////////////////////////////////////////////////////////////////////////////// - -SkImageRef::SkImageRef(const SkImageInfo& info, SkStreamRewindable* stream, - int sampleSize, SkBaseMutex* mutex) - : SkPixelRef(info, mutex), fErrorInDecoding(false) { - SkASSERT(stream); - stream->ref(); - fStream = stream; - fSampleSize = sampleSize; - fDoDither = true; - fPrev = fNext = NULL; - fFactory = NULL; - -#ifdef DUMP_IMAGEREF_LIFECYCLE - SkDebugf("add ImageRef %p [%d] data=%d\n", - this, this->info().fColorType, (int)stream->getLength()); -#endif -} - -SkImageRef::~SkImageRef() { - -#ifdef DUMP_IMAGEREF_LIFECYCLE - SkDebugf("delete ImageRef %p [%d] data=%d\n", - this, fConfig, (int)fStream->getLength()); -#endif - - fStream->unref(); - SkSafeUnref(fFactory); -} - -bool SkImageRef::getInfo(SkBitmap* bitmap) { - SkAutoMutexAcquire ac(this->mutex()); - - if (!this->prepareBitmap(SkImageDecoder::kDecodeBounds_Mode)) { - return false; - } - - SkASSERT(SkBitmap::kNo_Config != fBitmap.config()); - if (bitmap) { - bitmap->setConfig(fBitmap.config(), fBitmap.width(), fBitmap.height()); - } - return true; -} - -bool SkImageRef::isOpaque(SkBitmap* bitmap) { - if (bitmap && bitmap->pixelRef() == this) { - bitmap->lockPixels(); - // what about colortables?????? - bitmap->setAlphaType(fBitmap.alphaType()); - bitmap->unlockPixels(); - return true; - } - return false; -} - -SkImageDecoderFactory* SkImageRef::setDecoderFactory( - SkImageDecoderFactory* fact) { - SkRefCnt_SafeAssign(fFactory, fact); - return fact; -} - -/////////////////////////////////////////////////////////////////////////////// - -bool SkImageRef::onDecode(SkImageDecoder* codec, SkStreamRewindable* stream, - SkBitmap* bitmap, SkBitmap::Config config, - SkImageDecoder::Mode mode) { - return codec->decode(stream, bitmap, config, mode); -} - -bool SkImageRef::prepareBitmap(SkImageDecoder::Mode mode) { - - if (fErrorInDecoding) { - return false; - } - - if (NULL != fBitmap.getPixels() || - (SkBitmap::kNo_Config != fBitmap.config() && - SkImageDecoder::kDecodeBounds_Mode == mode)) { - return true; - } - - SkASSERT(fBitmap.getPixels() == NULL); - - if (!fStream->rewind()) { - SkDEBUGF(("Failed to rewind SkImageRef stream!")); - return false; - } - - SkImageDecoder* codec; - if (fFactory) { - codec = fFactory->newDecoder(fStream); - } else { - codec = SkImageDecoder::Factory(fStream); - } - - if (codec) { - SkAutoTDelete<SkImageDecoder> ad(codec); - - codec->setSampleSize(fSampleSize); - codec->setDitherImage(fDoDither); - if (this->onDecode(codec, fStream, &fBitmap, fBitmap.config(), mode)) { - return true; - } - } - -#ifdef DUMP_IMAGEREF_LIFECYCLE - if (NULL == codec) { - SkDebugf("--- ImageRef: <%s> failed to find codec\n", this->getURI()); - } else { - SkDebugf("--- ImageRef: <%s> failed in codec for %d mode\n", - this->getURI(), mode); - } -#endif - fErrorInDecoding = true; - fBitmap.reset(); - return false; -} - -void* SkImageRef::onLockPixels(SkColorTable** ct) { - if (NULL == fBitmap.getPixels()) { - (void)this->prepareBitmap(SkImageDecoder::kDecodePixels_Mode); - } - - if (ct) { - *ct = fBitmap.getColorTable(); - } - return fBitmap.getPixels(); -} - -size_t SkImageRef::ramUsed() const { - size_t size = 0; - - if (fBitmap.getPixels()) { - size = fBitmap.getSize(); - if (fBitmap.getColorTable()) { - size += fBitmap.getColorTable()->count() * sizeof(SkPMColor); - } - } - return size; -} - -/////////////////////////////////////////////////////////////////////////////// - -SkImageRef::SkImageRef(SkFlattenableReadBuffer& buffer, SkBaseMutex* mutex) - : INHERITED(buffer, mutex), fErrorInDecoding(false) { - fSampleSize = buffer.readInt(); - fDoDither = buffer.readBool(); - - size_t length = buffer.getArrayCount(); - fStream = SkNEW_ARGS(SkMemoryStream, (length)); - buffer.readByteArray((void*)fStream->getMemoryBase(), length); - - fPrev = fNext = NULL; - fFactory = NULL; -} - -void SkImageRef::flatten(SkFlattenableWriteBuffer& buffer) const { - this->INHERITED::flatten(buffer); - - buffer.writeInt(fSampleSize); - buffer.writeBool(fDoDither); - // FIXME: Consider moving this logic should go into writeStream itself. - // writeStream currently has no other callers, so this may be fine for - // now. - if (!fStream->rewind()) { - SkDEBUGF(("Failed to rewind SkImageRef stream!")); - buffer.write32(0); - } else { - // FIXME: Handle getLength properly here. Perhaps this class should - // take an SkStreamAsset. - buffer.writeStream(fStream, fStream->getLength()); - } -} diff --git a/chromium/third_party/skia/src/images/SkImageRefPool.cpp b/chromium/third_party/skia/src/images/SkImageRefPool.cpp deleted file mode 100644 index 0a3d7bf8cc4..00000000000 --- a/chromium/third_party/skia/src/images/SkImageRefPool.cpp +++ /dev/null @@ -1,192 +0,0 @@ - -/* - * Copyright 2011 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -#include "SkImageRefPool.h" -#include "SkImageRef.h" -#include "SkThread.h" - -SkImageRefPool::SkImageRefPool() { - fRAMBudget = 0; // means no explicit limit - fRAMUsed = 0; - fCount = 0; - fHead = fTail = NULL; -} - -SkImageRefPool::~SkImageRefPool() { - // SkASSERT(NULL == fHead); -} - -void SkImageRefPool::setRAMBudget(size_t size) { - if (fRAMBudget != size) { - fRAMBudget = size; - this->purgeIfNeeded(); - } -} - -void SkImageRefPool::justAddedPixels(SkImageRef* ref) { -#ifdef DUMP_IMAGEREF_LIFECYCLE - SkDebugf("=== ImagePool: add pixels %s [%d %d %d] bytes=%d heap=%d\n", - ref->getURI(), - ref->fBitmap.width(), ref->fBitmap.height(), - ref->fBitmap.bytesPerPixel(), - ref->fBitmap.getSize(), (int)fRAMUsed); -#endif - fRAMUsed += ref->ramUsed(); - this->purgeIfNeeded(); -} - -void SkImageRefPool::canLosePixels(SkImageRef* ref) { - // the refs near fHead have recently been released (used) - // if we purge, we purge from the tail - this->detach(ref); - this->addToHead(ref); - this->purgeIfNeeded(); -} - -void SkImageRefPool::purgeIfNeeded() { - // do nothing if we have a zero-budget (i.e. unlimited) - if (fRAMBudget != 0) { - this->setRAMUsed(fRAMBudget); - } -} - -void SkImageRefPool::setRAMUsed(size_t limit) { - SkImageRef* ref = fTail; - - while (NULL != ref && fRAMUsed > limit) { - // only purge it if its pixels are unlocked - if (!ref->isLocked() && ref->fBitmap.getPixels()) { - size_t size = ref->ramUsed(); - SkASSERT(size <= fRAMUsed); - fRAMUsed -= size; - -#ifdef DUMP_IMAGEREF_LIFECYCLE - SkDebugf("=== ImagePool: purge %s [%d %d %d] bytes=%d heap=%d\n", - ref->getURI(), - ref->fBitmap.width(), ref->fBitmap.height(), - ref->fBitmap.bytesPerPixel(), - (int)size, (int)fRAMUsed); -#endif - - // remember the bitmap config (don't call reset), - // just clear the pixel memory - ref->fBitmap.setPixels(NULL); - SkASSERT(NULL == ref->fBitmap.getPixels()); - } - ref = ref->fPrev; - } -} - -/////////////////////////////////////////////////////////////////////////////// - -void SkImageRefPool::addToHead(SkImageRef* ref) { - ref->fNext = fHead; - ref->fPrev = NULL; - - if (fHead) { - SkASSERT(NULL == fHead->fPrev); - fHead->fPrev = ref; - } - fHead = ref; - - if (NULL == fTail) { - fTail = ref; - } - fCount += 1; - SkASSERT(computeCount() == fCount); - - fRAMUsed += ref->ramUsed(); -} - -void SkImageRefPool::addToTail(SkImageRef* ref) { - ref->fNext = NULL; - ref->fPrev = fTail; - - if (fTail) { - SkASSERT(NULL == fTail->fNext); - fTail->fNext = ref; - } - fTail = ref; - - if (NULL == fHead) { - fHead = ref; - } - fCount += 1; - SkASSERT(computeCount() == fCount); - - fRAMUsed += ref->ramUsed(); -} - -void SkImageRefPool::detach(SkImageRef* ref) { - SkASSERT(fCount > 0); - - if (fHead == ref) { - fHead = ref->fNext; - } - if (fTail == ref) { - fTail = ref->fPrev; - } - if (ref->fPrev) { - ref->fPrev->fNext = ref->fNext; - } - if (ref->fNext) { - ref->fNext->fPrev = ref->fPrev; - } - - ref->fNext = ref->fPrev = NULL; - - fCount -= 1; - SkASSERT(computeCount() == fCount); - - SkASSERT(fRAMUsed >= ref->ramUsed()); - fRAMUsed -= ref->ramUsed(); -} - -int SkImageRefPool::computeCount() const { - SkImageRef* ref = fHead; - int count = 0; - - while (ref != NULL) { - count += 1; - ref = ref->fNext; - } - -#ifdef SK_DEBUG - ref = fTail; - int count2 = 0; - - while (ref != NULL) { - count2 += 1; - ref = ref->fPrev; - } - SkASSERT(count2 == count); -#endif - - return count; -} - -/////////////////////////////////////////////////////////////////////////////// - -#include "SkStream.h" - -void SkImageRefPool::dump() const { -#if defined(SK_DEBUG) || defined(DUMP_IMAGEREF_LIFECYCLE) - SkDebugf("ImagePool dump: bugdet: %d used: %d count: %d\n", - (int)fRAMBudget, (int)fRAMUsed, fCount); - - SkImageRef* ref = fHead; - - while (ref != NULL) { - SkDebugf(" [%3d %3d %d] ram=%d data=%d locked=%d %s\n", ref->fBitmap.width(), - ref->fBitmap.height(), ref->fBitmap.config(), - ref->ramUsed(), (int)ref->fStream->getLength(), - ref->isLocked(), ref->getURI()); - - ref = ref->fNext; - } -#endif -} diff --git a/chromium/third_party/skia/src/images/SkImageRefPool.h b/chromium/third_party/skia/src/images/SkImageRefPool.h deleted file mode 100644 index 1e74a6d077c..00000000000 --- a/chromium/third_party/skia/src/images/SkImageRefPool.h +++ /dev/null @@ -1,49 +0,0 @@ - -/* - * Copyright 2011 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -#ifndef SkImageRefPool_DEFINED -#define SkImageRefPool_DEFINED - -#include "SkTypes.h" - -class SkImageRef; -class SkImageRef_GlobalPool; - -class SkImageRefPool { -public: - SkImageRefPool(); - ~SkImageRefPool(); - - size_t getRAMBudget() const { return fRAMBudget; } - void setRAMBudget(size_t); - - size_t getRAMUsed() const { return fRAMUsed; } - void setRAMUsed(size_t limit); - - void addToHead(SkImageRef*); - void addToTail(SkImageRef*); - void detach(SkImageRef*); - - void dump() const; - -private: - size_t fRAMBudget; - size_t fRAMUsed; - - int fCount; - SkImageRef* fHead, *fTail; - - int computeCount() const; - - friend class SkImageRef_GlobalPool; - - void justAddedPixels(SkImageRef*); - void canLosePixels(SkImageRef*); - void purgeIfNeeded(); -}; - -#endif diff --git a/chromium/third_party/skia/src/images/SkImageRef_GlobalPool.cpp b/chromium/third_party/skia/src/images/SkImageRef_GlobalPool.cpp deleted file mode 100644 index f91cebabbf8..00000000000 --- a/chromium/third_party/skia/src/images/SkImageRef_GlobalPool.cpp +++ /dev/null @@ -1,100 +0,0 @@ - -/* - * Copyright 2011 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -#include "SkImageRef_GlobalPool.h" -#include "SkImageRefPool.h" -#include "SkThread.h" - -SK_DECLARE_STATIC_MUTEX(gGlobalPoolMutex); - -/* - * This returns the lazily-allocated global pool. It must be called - * from inside the guard mutex, so we safely only ever allocate 1. - */ -static SkImageRefPool* GetGlobalPool() { - static SkImageRefPool* gPool; - if (NULL == gPool) { - gPool = SkNEW(SkImageRefPool); - // call sk_atexit(...) when we have that, to free the global pool - } - return gPool; -} - -SkImageRef_GlobalPool::SkImageRef_GlobalPool(const SkImageInfo& info, - SkStreamRewindable* stream, - int sampleSize) - : SkImageRef(info, stream, sampleSize, &gGlobalPoolMutex) { - SkASSERT(&gGlobalPoolMutex == this->mutex()); - SkAutoMutexAcquire ac(gGlobalPoolMutex); - GetGlobalPool()->addToHead(this); -} - -SkImageRef_GlobalPool::~SkImageRef_GlobalPool() { - SkASSERT(&gGlobalPoolMutex == this->mutex()); - SkAutoMutexAcquire ac(gGlobalPoolMutex); - GetGlobalPool()->detach(this); -} - -/* By design, onUnlockPixels() already is inside the mutex-lock, - * and it is the (indirect) caller of onDecode(), therefore we can assume - * that we also are already inside the mutex. Hence, we can reference - * the global-pool directly. - */ -bool SkImageRef_GlobalPool::onDecode(SkImageDecoder* codec, SkStreamRewindable* stream, - SkBitmap* bitmap, SkBitmap::Config config, - SkImageDecoder::Mode mode) { - if (!this->INHERITED::onDecode(codec, stream, bitmap, config, mode)) { - return false; - } - if (mode == SkImageDecoder::kDecodePixels_Mode) { - // no need to grab the mutex here, it has already been acquired. - GetGlobalPool()->justAddedPixels(this); - } - return true; -} - -void SkImageRef_GlobalPool::onUnlockPixels() { - this->INHERITED::onUnlockPixels(); - - // by design, onUnlockPixels() already is inside the mutex-lock - GetGlobalPool()->canLosePixels(this); -} - -SkImageRef_GlobalPool::SkImageRef_GlobalPool(SkFlattenableReadBuffer& buffer) - : INHERITED(buffer, &gGlobalPoolMutex) { - SkASSERT(&gGlobalPoolMutex == this->mutex()); - SkAutoMutexAcquire ac(gGlobalPoolMutex); - GetGlobalPool()->addToHead(this); -} - -/////////////////////////////////////////////////////////////////////////////// -// global imagerefpool wrappers - -size_t SkImageRef_GlobalPool::GetRAMBudget() { - SkAutoMutexAcquire ac(gGlobalPoolMutex); - return GetGlobalPool()->getRAMBudget(); -} - -void SkImageRef_GlobalPool::SetRAMBudget(size_t size) { - SkAutoMutexAcquire ac(gGlobalPoolMutex); - GetGlobalPool()->setRAMBudget(size); -} - -size_t SkImageRef_GlobalPool::GetRAMUsed() { - SkAutoMutexAcquire ac(gGlobalPoolMutex); - return GetGlobalPool()->getRAMUsed(); -} - -void SkImageRef_GlobalPool::SetRAMUsed(size_t usage) { - SkAutoMutexAcquire ac(gGlobalPoolMutex); - GetGlobalPool()->setRAMUsed(usage); -} - -void SkImageRef_GlobalPool::DumpPool() { - SkAutoMutexAcquire ac(gGlobalPoolMutex); - GetGlobalPool()->dump(); -} diff --git a/chromium/third_party/skia/src/images/SkImageRef_ashmem.cpp b/chromium/third_party/skia/src/images/SkImageRef_ashmem.cpp deleted file mode 100644 index 269199faf84..00000000000 --- a/chromium/third_party/skia/src/images/SkImageRef_ashmem.cpp +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright 2011 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "SkImageRef_ashmem.h" -#include "SkImageDecoder.h" -#include "SkFlattenableBuffers.h" -#include "SkThread.h" - -#include "android/ashmem.h" - -#include <sys/mman.h> -#include <unistd.h> - -//#define TRACE_ASH_PURGE // just trace purges - -#ifdef DUMP_IMAGEREF_LIFECYCLE - #define DUMP_ASHMEM_LIFECYCLE -#else -// #define DUMP_ASHMEM_LIFECYCLE -#endif - -// ashmem likes lengths on page boundaries -static size_t roundToPageSize(size_t size) { - const size_t mask = getpagesize() - 1; - size_t newsize = (size + mask) & ~mask; -// SkDebugf("---- oldsize %d newsize %d\n", size, newsize); - return newsize; -} - -SkImageRef_ashmem::SkImageRef_ashmem(const SkImageInfo& info, - SkStreamRewindable* stream, - int sampleSize) - : SkImageRef(info, stream, sampleSize) -{ - fRec.fFD = -1; - fRec.fAddr = NULL; - fRec.fSize = 0; - fRec.fPinned = false; - - fCT = NULL; -} - -SkImageRef_ashmem::~SkImageRef_ashmem() { - SkSafeUnref(fCT); - this->closeFD(); -} - -void SkImageRef_ashmem::closeFD() { - if (-1 != fRec.fFD) { -#ifdef DUMP_ASHMEM_LIFECYCLE - SkDebugf("=== ashmem close %d\n", fRec.fFD); -#endif - SkASSERT(fRec.fAddr); - SkASSERT(fRec.fSize); - munmap(fRec.fAddr, fRec.fSize); - close(fRec.fFD); - fRec.fFD = -1; - } -} - -/////////////////////////////////////////////////////////////////////////////// - -class AshmemAllocator : public SkBitmap::Allocator { -public: - AshmemAllocator(SkAshmemRec* rec, const char name[]) - : fRec(rec), fName(name) {} - - virtual bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) { - const size_t size = roundToPageSize(bm->getSize()); - int fd = fRec->fFD; - void* addr = fRec->fAddr; - - SkASSERT(!fRec->fPinned); - - if (-1 == fd) { - SkASSERT(NULL == addr); - SkASSERT(0 == fRec->fSize); - - fd = ashmem_create_region(fName, size); -#ifdef DUMP_ASHMEM_LIFECYCLE - SkDebugf("=== ashmem_create_region %s size=%d fd=%d\n", fName, size, fd); -#endif - if (-1 == fd) { - SkDebugf("------- imageref_ashmem create failed <%s> %d\n", - fName, size); - return false; - } - - int err = ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE); - if (err) { - SkDebugf("------ ashmem_set_prot_region(%d) failed %d\n", - fd, err); - close(fd); - return false; - } - - addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); - if (-1 == (long)addr) { - SkDebugf("---------- mmap failed for imageref_ashmem size=%d\n", - size); - close(fd); - return false; - } - - fRec->fFD = fd; - fRec->fAddr = addr; - fRec->fSize = size; - } else { - SkASSERT(addr); - SkASSERT(size == fRec->fSize); - (void)ashmem_pin_region(fd, 0, 0); - } - - bm->setPixels(addr, ct); - fRec->fPinned = true; - return true; - } - -private: - // we just point to our caller's memory, these are not copies - SkAshmemRec* fRec; - const char* fName; -}; - -bool SkImageRef_ashmem::onDecode(SkImageDecoder* codec, SkStreamRewindable* stream, - SkBitmap* bitmap, SkBitmap::Config config, - SkImageDecoder::Mode mode) { - - if (SkImageDecoder::kDecodeBounds_Mode == mode) { - return this->INHERITED::onDecode(codec, stream, bitmap, config, mode); - } - - // Ashmem memory is guaranteed to be initialized to 0. - codec->setSkipWritingZeroes(true); - - AshmemAllocator alloc(&fRec, this->getURI()); - - codec->setAllocator(&alloc); - bool success = this->INHERITED::onDecode(codec, stream, bitmap, config, - mode); - // remove the allocator, since its on the stack - codec->setAllocator(NULL); - - if (success) { - // remember the colortable (if any) - SkRefCnt_SafeAssign(fCT, bitmap->getColorTable()); - return true; - } else { - if (fRec.fPinned) { - ashmem_unpin_region(fRec.fFD, 0, 0); - fRec.fPinned = false; - } - this->closeFD(); - return false; - } -} - -void* SkImageRef_ashmem::onLockPixels(SkColorTable** ct) { - SkASSERT(fBitmap.getPixels() == NULL); - SkASSERT(fBitmap.getColorTable() == NULL); - - // fast case: check if we can just pin and get the cached data - if (-1 != fRec.fFD) { - SkASSERT(fRec.fAddr); - SkASSERT(!fRec.fPinned); - int pin = ashmem_pin_region(fRec.fFD, 0, 0); - - if (ASHMEM_NOT_PURGED == pin) { // yea, fast case! - fBitmap.setPixels(fRec.fAddr, fCT); - fRec.fPinned = true; - } else if (ASHMEM_WAS_PURGED == pin) { - ashmem_unpin_region(fRec.fFD, 0, 0); - // let go of our colortable if we lost the pixels. Well get it back - // again when we re-decode - if (fCT) { - fCT->unref(); - fCT = NULL; - } -#if defined(DUMP_ASHMEM_LIFECYCLE) || defined(TRACE_ASH_PURGE) - SkDebugf("===== ashmem purged %d\n", fBitmap.getSize()); -#endif - } else { - SkDebugf("===== ashmem pin_region(%d) returned %d\n", fRec.fFD, pin); - // return null result for failure - if (ct) { - *ct = NULL; - } - return NULL; - } - } else { - // no FD, will create an ashmem region in allocator - } - - return this->INHERITED::onLockPixels(ct); -} - -void SkImageRef_ashmem::onUnlockPixels() { - this->INHERITED::onUnlockPixels(); - - if (-1 != fRec.fFD) { - SkASSERT(fRec.fAddr); - SkASSERT(fRec.fPinned); - - ashmem_unpin_region(fRec.fFD, 0, 0); - fRec.fPinned = false; - } - - // we clear this with or without an error, since we've either closed or - // unpinned the region - fBitmap.setPixels(NULL, NULL); -} - -void SkImageRef_ashmem::flatten(SkFlattenableWriteBuffer& buffer) const { - this->INHERITED::flatten(buffer); - buffer.writeString(getURI()); -} - -SkImageRef_ashmem::SkImageRef_ashmem(SkFlattenableReadBuffer& buffer) - : INHERITED(buffer) { - fRec.fFD = -1; - fRec.fAddr = NULL; - fRec.fSize = 0; - fRec.fPinned = false; - fCT = NULL; - - SkString uri; - buffer.readString(&uri); - this->setURI(uri); -} diff --git a/chromium/third_party/skia/src/images/SkImageRef_ashmem.h b/chromium/third_party/skia/src/images/SkImageRef_ashmem.h deleted file mode 100644 index a2652fbc300..00000000000 --- a/chromium/third_party/skia/src/images/SkImageRef_ashmem.h +++ /dev/null @@ -1,47 +0,0 @@ - -/* - * Copyright 2011 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -#ifndef SkImageRef_ashmem_DEFINED -#define SkImageRef_ashmem_DEFINED - -#include "SkImageRef.h" - -struct SkAshmemRec { - int fFD; - void* fAddr; - size_t fSize; - bool fPinned; -}; - -class SkImageRef_ashmem : public SkImageRef { -public: - SkImageRef_ashmem(const SkImageInfo&, SkStreamRewindable*, int sampleSize = 1); - virtual ~SkImageRef_ashmem(); - - SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkImageRef_ashmem) - -protected: - SkImageRef_ashmem(SkFlattenableReadBuffer&); - virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; - - virtual bool onDecode(SkImageDecoder* codec, SkStreamRewindable* stream, - SkBitmap* bitmap, SkBitmap::Config config, - SkImageDecoder::Mode mode); - - virtual void* onLockPixels(SkColorTable**); - virtual void onUnlockPixels(); - -private: - void closeFD(); - - SkColorTable* fCT; - SkAshmemRec fRec; - - typedef SkImageRef INHERITED; -}; - -#endif diff --git a/chromium/third_party/skia/src/images/SkImages.cpp b/chromium/third_party/skia/src/images/SkImages.cpp deleted file mode 100644 index 5b6bf6b7ce9..00000000000 --- a/chromium/third_party/skia/src/images/SkImages.cpp +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2012 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "SkFlattenable.h" -#include "SkImageRef_GlobalPool.h" -#include "SkImages.h" - -#ifdef SK_BUILD_FOR_ANDROID -#include "SkImageRef_ashmem.h" -#endif - -void SkImages::InitializeFlattenables() { - SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkImageRef_GlobalPool) -#ifdef SK_BUILD_FOR_ANDROID - SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkImageRef_ashmem) -#endif -} diff --git a/chromium/third_party/skia/src/images/SkMovie_gif.cpp b/chromium/third_party/skia/src/images/SkMovie_gif.cpp index b6d068a391c..decefd5acc5 100644 --- a/chromium/third_party/skia/src/images/SkMovie_gif.cpp +++ b/chromium/third_party/skia/src/images/SkMovie_gif.cpp @@ -364,13 +364,11 @@ bool SkGIFMovie::onGetBitmap(SkBitmap* bm) startIndex = 0; // create bitmap - bm->setConfig(SkBitmap::kARGB_8888_Config, width, height, 0); - if (!bm->allocPixels(NULL)) { + if (!bm->allocPixels(SkImageInfo::MakeN32Premul(width, height))) { return false; } // create bitmap for backup - fBackup.setConfig(SkBitmap::kARGB_8888_Config, width, height, 0); - if (!fBackup.allocPixels(NULL)) { + if (!fBackup.allocPixels(SkImageInfo::MakeN32Premul(width, height))) { return false; } } else if (startIndex > fCurrIndex) { diff --git a/chromium/third_party/skia/src/images/SkScaledBitmapSampler.cpp b/chromium/third_party/skia/src/images/SkScaledBitmapSampler.cpp index 03ee2eed62b..d78502d2bbd 100644 --- a/chromium/third_party/skia/src/images/SkScaledBitmapSampler.cpp +++ b/chromium/third_party/skia/src/images/SkScaledBitmapSampler.cpp @@ -25,7 +25,8 @@ static bool Sample_Gray_D8888(void* SK_RESTRICT dstRow, return false; } -static SkScaledBitmapSampler::RowProc get_gray_to_8888_proc(const SkImageDecoder& decoder) { +static SkScaledBitmapSampler::RowProc +get_gray_to_8888_proc(const SkScaledBitmapSampler::Options& opts) { // Dither, unpremul, and skipZeroes have no effect return Sample_Gray_D8888; } @@ -41,7 +42,8 @@ static bool Sample_RGBx_D8888(void* SK_RESTRICT dstRow, return false; } -static SkScaledBitmapSampler::RowProc get_RGBx_to_8888_proc(const SkImageDecoder& decoder) { +static SkScaledBitmapSampler::RowProc +get_RGBx_to_8888_proc(const SkScaledBitmapSampler::Options& opts) { // Dither, unpremul, and skipZeroes have no effect return Sample_RGBx_D8888; } @@ -92,15 +94,16 @@ static bool Sample_RGBA_D8888_SkipZ(void* SK_RESTRICT dstRow, return alphaMask != 0xFF; } -static SkScaledBitmapSampler::RowProc get_RGBA_to_8888_proc(const SkImageDecoder& decoder) { +static SkScaledBitmapSampler::RowProc +get_RGBA_to_8888_proc(const SkScaledBitmapSampler::Options& opts) { // Dither has no effect. - if (decoder.getRequireUnpremultipliedColors()) { + if (!opts.fPremultiplyAlpha) { // We could check each component for a zero, at the expense of extra checks. // For now, just return unpremul. return Sample_RGBA_D8888_Unpremul; } // Supply the versions that premultiply the colors - if (decoder.getSkipWritingZeroes()) { + if (opts.fSkipZeros) { return Sample_RGBA_D8888_SkipZ; } return Sample_RGBA_D8888; @@ -131,9 +134,10 @@ static bool Sample_Gray_D565_D(void* SK_RESTRICT dstRow, return false; } -static SkScaledBitmapSampler::RowProc get_gray_to_565_proc(const SkImageDecoder& decoder) { +static SkScaledBitmapSampler::RowProc +get_gray_to_565_proc(const SkScaledBitmapSampler::Options& opts) { // Unpremul and skip zeroes make no difference - if (decoder.getDitherImage()) { + if (opts.fDither) { return Sample_Gray_D565_D; } return Sample_Gray_D565; @@ -163,9 +167,10 @@ static bool Sample_RGBx_D565_D(void* SK_RESTRICT dstRow, return false; } -static SkScaledBitmapSampler::RowProc get_RGBx_to_565_proc(const SkImageDecoder& decoder) { +static SkScaledBitmapSampler::RowProc +get_RGBx_to_565_proc(const SkScaledBitmapSampler::Options& opts) { // Unpremul and skip zeroes make no difference - if (decoder.getDitherImage()) { + if (opts.fDither) { return Sample_RGBx_D565_D; } return Sample_RGBx_D565; @@ -184,7 +189,8 @@ static bool Sample_D565_D565(void* SK_RESTRICT dstRow, return false; } -static SkScaledBitmapSampler::RowProc get_565_to_565_proc(const SkImageDecoder& decoder) { +static SkScaledBitmapSampler::RowProc +get_565_to_565_proc(const SkScaledBitmapSampler::Options& opts) { // Unpremul, dither, and skip zeroes have no effect return Sample_D565_D565; } @@ -216,9 +222,10 @@ static bool Sample_Gray_D4444_D(void* SK_RESTRICT dstRow, return false; } -static SkScaledBitmapSampler::RowProc get_gray_to_4444_proc(const SkImageDecoder& decoder) { +static SkScaledBitmapSampler::RowProc +get_gray_to_4444_proc(const SkScaledBitmapSampler::Options& opts) { // Skip zeroes and unpremul make no difference - if (decoder.getDitherImage()) { + if (opts.fDither) { return Sample_Gray_D4444_D; } return Sample_Gray_D4444; @@ -249,9 +256,10 @@ static bool Sample_RGBx_D4444_D(void* SK_RESTRICT dstRow, return false; } -static SkScaledBitmapSampler::RowProc get_RGBx_to_4444_proc(const SkImageDecoder& decoder) { +static SkScaledBitmapSampler::RowProc +get_RGBx_to_4444_proc(const SkScaledBitmapSampler::Options& opts) { // Skip zeroes and unpremul make no difference - if (decoder.getDitherImage()) { + if (opts.fDither) { return Sample_RGBx_D4444_D; } return Sample_RGBx_D4444; @@ -331,19 +339,19 @@ static bool Sample_RGBA_D4444_D_SkipZ(void* SK_RESTRICT dstRow, return alphaMask != 0xFF; } -static SkScaledBitmapSampler::RowProc get_RGBA_to_4444_proc(const SkImageDecoder& decoder) { - if (decoder.getRequireUnpremultipliedColors()) { +static SkScaledBitmapSampler::RowProc +get_RGBA_to_4444_proc(const SkScaledBitmapSampler::Options& opts) { + if (!opts.fPremultiplyAlpha) { // Unpremultiplied is not supported for 4444 return NULL; } - const bool dither = decoder.getDitherImage(); - if (decoder.getSkipWritingZeroes()) { - if (dither) { + if (opts.fSkipZeros) { + if (opts.fDither) { return Sample_RGBA_D4444_D_SkipZ; } return Sample_RGBA_D4444_SkipZ; } - if (dither) { + if (opts.fDither) { return Sample_RGBA_D4444_D; } return Sample_RGBA_D4444; @@ -386,13 +394,14 @@ static bool Sample_Index_D8888_SkipZ(void* SK_RESTRICT dstRow, return cc != A32_MASK_IN_PLACE; } -static SkScaledBitmapSampler::RowProc get_index_to_8888_proc(const SkImageDecoder& decoder) { - if (decoder.getRequireUnpremultipliedColors()) { +static SkScaledBitmapSampler::RowProc +get_index_to_8888_proc(const SkScaledBitmapSampler::Options& opts) { + if (!opts.fPremultiplyAlpha) { // Unpremultiplied is not supported for an index source. return NULL; } // Dither makes no difference - if (decoder.getSkipWritingZeroes()) { + if (opts.fSkipZeros) { return Sample_Index_D8888_SkipZ; } return Sample_Index_D8888; @@ -426,9 +435,10 @@ static bool Sample_Index_D565_D(void* SK_RESTRICT dstRow, return false; } -static SkScaledBitmapSampler::RowProc get_index_to_565_proc(const SkImageDecoder& decoder) { +static SkScaledBitmapSampler::RowProc +get_index_to_565_proc(const SkScaledBitmapSampler::Options& opts) { // Unpremultiplied and skip zeroes make no difference - if (decoder.getDitherImage()) { + if (opts.fDither) { return Sample_Index_D565_D; } return Sample_Index_D565; @@ -502,19 +512,19 @@ static bool Sample_Index_D4444_D_SkipZ(void* SK_RESTRICT dstRow, return cc != A32_MASK_IN_PLACE; } -static SkScaledBitmapSampler::RowProc get_index_to_4444_proc(const SkImageDecoder& decoder) { +static SkScaledBitmapSampler::RowProc +get_index_to_4444_proc(const SkScaledBitmapSampler::Options& opts) { // Unpremul not allowed - if (decoder.getRequireUnpremultipliedColors()) { + if (!opts.fPremultiplyAlpha) { return NULL; } - const bool dither = decoder.getDitherImage(); - if (decoder.getSkipWritingZeroes()) { - if (dither) { + if (opts.fSkipZeros) { + if (opts.fDither) { return Sample_Index_D4444_D_SkipZ; } return Sample_Index_D4444_SkipZ; } - if (dither) { + if (opts.fDither) { return Sample_Index_D4444_D; } return Sample_Index_D4444; @@ -535,9 +545,10 @@ static bool Sample_Index_DI(void* SK_RESTRICT dstRow, return false; } -static SkScaledBitmapSampler::RowProc get_index_to_index_proc(const SkImageDecoder& decoder) { +static SkScaledBitmapSampler::RowProc +get_index_to_index_proc(const SkScaledBitmapSampler::Options& opts) { // Unpremul not allowed - if (decoder.getRequireUnpremultipliedColors()) { + if (!opts.fPremultiplyAlpha) { return NULL; } // Ignore dither and skip zeroes @@ -557,15 +568,16 @@ static bool Sample_Gray_DA8(void* SK_RESTRICT dstRow, return true; } -static SkScaledBitmapSampler::RowProc get_gray_to_A8_proc(const SkImageDecoder& decoder) { - if (decoder.getRequireUnpremultipliedColors()) { +static SkScaledBitmapSampler::RowProc +get_gray_to_A8_proc(const SkScaledBitmapSampler::Options& opts) { + if (!opts.fPremultiplyAlpha) { return NULL; } // Ignore skip and dither. return Sample_Gray_DA8; } -typedef SkScaledBitmapSampler::RowProc (*RowProcChooser)(const SkImageDecoder& decoder); +typedef SkScaledBitmapSampler::RowProc (*RowProcChooser)(const SkScaledBitmapSampler::Options&); /////////////////////////////////////////////////////////////////////////////// #include "SkScaledBitmapSampler.h" @@ -613,7 +625,7 @@ SkScaledBitmapSampler::SkScaledBitmapSampler(int width, int height, } bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc, - const SkImageDecoder& decoder, + const Options& opts, const SkPMColor ctable[]) { static const RowProcChooser gProcChoosers[] = { get_gray_to_8888_proc, @@ -684,20 +696,20 @@ bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc, return false; } - switch (dst->config()) { - case SkBitmap::kARGB_8888_Config: + switch (dst->colorType()) { + case kN32_SkColorType: index += 0 * gProcDstConfigSpan; break; - case SkBitmap::kRGB_565_Config: + case kRGB_565_SkColorType: index += 1 * gProcDstConfigSpan; break; - case SkBitmap::kARGB_4444_Config: + case kARGB_4444_SkColorType: index += 2 * gProcDstConfigSpan; break; - case SkBitmap::kIndex8_Config: + case kIndex_8_SkColorType: index += 3 * gProcDstConfigSpan; break; - case SkBitmap::kA8_Config: + case kAlpha_8_SkColorType: index += 4 * gProcDstConfigSpan; break; default: @@ -708,7 +720,7 @@ bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc, if (NULL == chooser) { fRowProc = NULL; } else { - fRowProc = chooser(decoder); + fRowProc = chooser(opts); } fDstRow = (char*)dst->getPixels(); fDstRowBytes = dst->rowBytes(); @@ -716,6 +728,12 @@ bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc, return fRowProc != NULL; } +bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc, + const SkImageDecoder& decoder, + const SkPMColor ctable[]) { + return this->begin(dst, sc, Options(decoder), ctable); +} + bool SkScaledBitmapSampler::next(const uint8_t* SK_RESTRICT src) { SkASSERT(kInterlaced_SampleMode != fSampleMode); SkDEBUGCODE(fSampleMode = kConsecutive_SampleMode); @@ -824,17 +842,23 @@ protected: void test_row_proc_choice(); void test_row_proc_choice() { + const SkColorType colorTypes[] = { + kAlpha_8_SkColorType, kIndex_8_SkColorType, kRGB_565_SkColorType, kARGB_4444_SkColorType, + kN32_SkColorType + }; + SkBitmap dummyBitmap; DummyDecoder dummyDecoder; size_t procCounter = 0; for (int sc = SkScaledBitmapSampler::kGray; sc <= SkScaledBitmapSampler::kRGB_565; ++sc) { - for (int c = SkBitmap::kA8_Config; c <= SkBitmap::kARGB_8888_Config; ++c) { + for (size_t c = 0; c < SK_ARRAY_COUNT(colorTypes); ++c) { for (int unpremul = 0; unpremul <= 1; ++unpremul) { for (int dither = 0; dither <= 1; ++dither) { // Arbitrary width/height/sampleSize to allow SkScaledBitmapSampler to // be considered valid. SkScaledBitmapSampler sampler(10, 10, 1); - dummyBitmap.setConfig((SkBitmap::Config) c, 10, 10); + dummyBitmap.setInfo(SkImageInfo::Make(10, 10, + colorTypes[c], kPremul_SkAlphaType)); dummyDecoder.setDitherImage(SkToBool(dither)); dummyDecoder.setRequireUnpremultipliedColors(SkToBool(unpremul)); sampler.begin(&dummyBitmap, (SkScaledBitmapSampler::SrcConfig) sc, diff --git a/chromium/third_party/skia/src/images/SkScaledBitmapSampler.h b/chromium/third_party/skia/src/images/SkScaledBitmapSampler.h index e6c4577174c..90c4142bdfb 100644 --- a/chromium/third_party/skia/src/images/SkScaledBitmapSampler.h +++ b/chromium/third_party/skia/src/images/SkScaledBitmapSampler.h @@ -34,11 +34,24 @@ public: kRGB_565 // 2 bytes per pixel }; + struct Options { + bool fDither; + bool fPremultiplyAlpha; + bool fSkipZeros; + explicit Options(const SkImageDecoder &dec) + : fDither(dec.getDitherImage()) + , fPremultiplyAlpha(!dec.getRequireUnpremultipliedColors()) + , fSkipZeros(dec.getSkipWritingZeroes()) + { } + }; + // Given a dst bitmap (with pixels already allocated) and a src-config, // prepares iterator to process the src colors and write them into dst. // Returns false if the request cannot be fulfulled. bool begin(SkBitmap* dst, SrcConfig sc, const SkImageDecoder& decoder, const SkPMColor* = NULL); + bool begin(SkBitmap* dst, SrcConfig sc, const Options& opts, + const SkPMColor* = NULL); // call with row of src pixels, for y = 0...scaledHeight-1. // returns true if the row had non-opaque alpha in it bool next(const uint8_t* SK_RESTRICT src); diff --git a/chromium/third_party/skia/src/images/SkStreamHelpers.cpp b/chromium/third_party/skia/src/images/SkStreamHelpers.cpp index 3e9ee45345b..c7c66b4b0fa 100644 --- a/chromium/third_party/skia/src/images/SkStreamHelpers.cpp +++ b/chromium/third_party/skia/src/images/SkStreamHelpers.cpp @@ -5,6 +5,7 @@ * found in the LICENSE file. */ +#include "SkData.h" #include "SkStream.h" #include "SkStreamHelpers.h" #include "SkTypes.h" @@ -38,3 +39,29 @@ size_t CopyStreamToStorage(SkAutoMalloc* storage, SkStream* stream) { tempStream.copyTo(dst); return length; } + +SkData *CopyStreamToData(SkStream* stream) { + SkASSERT(stream != NULL); + + if (stream->hasLength()) { + const size_t length = stream->getLength(); + void* dst = sk_malloc_throw(length); + if (stream->read(dst, length) != length) { + return 0; + } + return SkData::NewFromMalloc(dst, length); + } + + SkDynamicMemoryWStream tempStream; + // Arbitrary buffer size. + const size_t bufferSize = 256 * 1024; // 256KB + char buffer[bufferSize]; + SkDEBUGCODE(size_t debugLength = 0;) + do { + size_t bytesRead = stream->read(buffer, bufferSize); + tempStream.write(buffer, bytesRead); + SkDEBUGCODE(debugLength += bytesRead); + SkASSERT(tempStream.bytesWritten() == debugLength); + } while (!stream->isAtEnd()); + return tempStream.copyToData(); +} diff --git a/chromium/third_party/skia/src/images/SkStreamHelpers.h b/chromium/third_party/skia/src/images/SkStreamHelpers.h index 7e766b7eccc..008dd8e17a0 100644 --- a/chromium/third_party/skia/src/images/SkStreamHelpers.h +++ b/chromium/third_party/skia/src/images/SkStreamHelpers.h @@ -10,6 +10,7 @@ class SkAutoMalloc; class SkStream; +class SkData; /** * Copy the provided stream to memory allocated by storage. @@ -24,4 +25,12 @@ class SkStream; */ size_t CopyStreamToStorage(SkAutoMalloc* storage, SkStream* stream); +/** + * Copy the provided stream to an SkData variable. Used by SkImageDecoder_libktx. + * @param stream SkStream to be copied into data. + * @return SkData* The resulting SkData after the copy. This data will have a + * ref count of one upon return and belongs to the caller. Returns NULL on failure. + */ +SkData *CopyStreamToData(SkStream* stream); + #endif // SkStreamHelpers_DEFINED |