| Index: src/ports/SkImageDecoder_CG.cpp
|
| diff --git a/src/ports/SkImageDecoder_CG.cpp b/src/ports/SkImageDecoder_CG.cpp
|
| index c4446ae16d67ef5671c817af569f188a73fe177d..ead0ed6506ff19d5c602d541a87543620bad291e 100644
|
| --- a/src/ports/SkImageDecoder_CG.cpp
|
| +++ b/src/ports/SkImageDecoder_CG.cpp
|
| @@ -11,7 +11,6 @@
|
| #include "SkCGUtils.h"
|
| #include "SkColorPriv.h"
|
| #include "SkData.h"
|
| -#include "SkImageDecoder.h"
|
| #include "SkImageEncoder.h"
|
| #include "SkMovie.h"
|
| #include "SkStream.h"
|
| @@ -29,210 +28,6 @@
|
| #include <MobileCoreServices/MobileCoreServices.h>
|
| #endif
|
|
|
| -static void data_unref_proc(void* skdata, const void*, size_t) {
|
| - SkASSERT(skdata);
|
| - static_cast<SkData*>(skdata)->unref();
|
| -}
|
| -
|
| -static CGDataProviderRef SkStreamToDataProvider(SkStream* stream) {
|
| - // TODO: use callbacks, so we don't have to load all the data into RAM
|
| - SkData* skdata = SkCopyStreamToData(stream).release();
|
| - if (!skdata) {
|
| - return nullptr;
|
| - }
|
| -
|
| - return CGDataProviderCreateWithData(skdata, skdata->data(), skdata->size(), data_unref_proc);
|
| -}
|
| -
|
| -static CGImageSourceRef SkStreamToCGImageSource(SkStream* stream) {
|
| - CGDataProviderRef data = SkStreamToDataProvider(stream);
|
| - if (!data) {
|
| - return nullptr;
|
| - }
|
| - CGImageSourceRef imageSrc = CGImageSourceCreateWithDataProvider(data, 0);
|
| - CGDataProviderRelease(data);
|
| - return imageSrc;
|
| -}
|
| -
|
| -class SkImageDecoder_CG : public SkImageDecoder {
|
| -protected:
|
| - virtual Result onDecode(SkStream* stream, SkBitmap* bm, Mode);
|
| -};
|
| -
|
| -static void argb_4444_force_opaque(void* row, int count) {
|
| - uint16_t* row16 = (uint16_t*)row;
|
| - for (int i = 0; i < count; ++i) {
|
| - row16[i] |= 0xF000;
|
| - }
|
| -}
|
| -
|
| -static void argb_8888_force_opaque(void* row, int count) {
|
| - // can use RGBA or BGRA, they have the same shift for alpha
|
| - const uint32_t alphaMask = 0xFF << SK_RGBA_A32_SHIFT;
|
| - uint32_t* row32 = (uint32_t*)row;
|
| - for (int i = 0; i < count; ++i) {
|
| - row32[i] |= alphaMask;
|
| - }
|
| -}
|
| -
|
| -static void alpha_8_force_opaque(void* row, int count) {
|
| - memset(row, 0xFF, count);
|
| -}
|
| -
|
| -static void force_opaque(SkBitmap* bm) {
|
| - SkAutoLockPixels alp(*bm);
|
| - if (!bm->getPixels()) {
|
| - return;
|
| - }
|
| -
|
| - void (*proc)(void*, int);
|
| - switch (bm->colorType()) {
|
| - case kARGB_4444_SkColorType:
|
| - proc = argb_4444_force_opaque;
|
| - break;
|
| - case kRGBA_8888_SkColorType:
|
| - case kBGRA_8888_SkColorType:
|
| - proc = argb_8888_force_opaque;
|
| - break;
|
| - case kAlpha_8_SkColorType:
|
| - proc = alpha_8_force_opaque;
|
| - break;
|
| - default:
|
| - return;
|
| - }
|
| -
|
| - char* row = (char*)bm->getPixels();
|
| - for (int y = 0; y < bm->height(); ++y) {
|
| - proc(row, bm->width());
|
| - row += bm->rowBytes();
|
| - }
|
| - bm->setAlphaType(kOpaque_SkAlphaType);
|
| -}
|
| -
|
| -#define BITMAP_INFO (kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast)
|
| -
|
| -class AutoCFDataRelease {
|
| - CFDataRef fDR;
|
| -public:
|
| - AutoCFDataRelease(CFDataRef dr) : fDR(dr) {}
|
| - ~AutoCFDataRelease() { if (fDR) { CFRelease(fDR); } }
|
| -
|
| - operator CFDataRef () { return fDR; }
|
| -};
|
| -
|
| -static bool colorspace_is_sRGB(CGColorSpaceRef cs) {
|
| -#ifdef SK_BUILD_FOR_IOS
|
| - return true; // iOS seems to define itself to always return sRGB <reed>
|
| -#else
|
| - AutoCFDataRelease data(CGColorSpaceCopyICCProfile(cs));
|
| - if (data) {
|
| - // found by inspection -- need a cleaner way to sniff a profile
|
| - const CFIndex ICC_PROFILE_OFFSET_TO_SRGB_TAG = 52;
|
| -
|
| - if (CFDataGetLength(data) >= ICC_PROFILE_OFFSET_TO_SRGB_TAG + 4) {
|
| - return !memcmp(CFDataGetBytePtr(data) + ICC_PROFILE_OFFSET_TO_SRGB_TAG, "sRGB", 4);
|
| - }
|
| - }
|
| - return false;
|
| -#endif
|
| -}
|
| -
|
| -SkImageDecoder::Result SkImageDecoder_CG::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
|
| - CGImageSourceRef imageSrc = SkStreamToCGImageSource(stream);
|
| -
|
| - if (nullptr == imageSrc) {
|
| - return kFailure;
|
| - }
|
| - SkAutoTCallVProc<const void, CFRelease> arsrc(imageSrc);
|
| -
|
| - CGImageRef image = CGImageSourceCreateImageAtIndex(imageSrc, 0, nullptr);
|
| - if (nullptr == image) {
|
| - return kFailure;
|
| - }
|
| - SkAutoTCallVProc<CGImage, CGImageRelease> arimage(image);
|
| -
|
| - const int width = SkToInt(CGImageGetWidth(image));
|
| - const int height = SkToInt(CGImageGetHeight(image));
|
| - SkColorProfileType cpType = kLinear_SkColorProfileType;
|
| -
|
| - CGColorSpaceRef cs = CGImageGetColorSpace(image);
|
| - if (cs) {
|
| - CGColorSpaceModel m = CGColorSpaceGetModel(cs);
|
| - if (kCGColorSpaceModelRGB == m && colorspace_is_sRGB(cs)) {
|
| - cpType = kSRGB_SkColorProfileType;
|
| - }
|
| - }
|
| -
|
| - SkAlphaType at = kPremul_SkAlphaType;
|
| - switch (CGImageGetAlphaInfo(image)) {
|
| - case kCGImageAlphaNone:
|
| - case kCGImageAlphaNoneSkipLast:
|
| - case kCGImageAlphaNoneSkipFirst:
|
| - at = kOpaque_SkAlphaType;
|
| - break;
|
| - default:
|
| - break;
|
| - }
|
| -
|
| - bm->setInfo(SkImageInfo::Make(width, height, kN32_SkColorType, at, cpType));
|
| - if (SkImageDecoder::kDecodeBounds_Mode == mode) {
|
| - return kSuccess;
|
| - }
|
| -
|
| - if (!this->allocPixelRef(bm, nullptr)) {
|
| - return kFailure;
|
| - }
|
| -
|
| - SkAutoLockPixels alp(*bm);
|
| -
|
| - if (!SkCopyPixelsFromCGImage(bm->info(), bm->rowBytes(), bm->getPixels(), image)) {
|
| - return kFailure;
|
| - }
|
| -
|
| - CGImageAlphaInfo info = CGImageGetAlphaInfo(image);
|
| - switch (info) {
|
| - case kCGImageAlphaNone:
|
| - case kCGImageAlphaNoneSkipLast:
|
| - case kCGImageAlphaNoneSkipFirst:
|
| - // We're opaque, but we can't rely on the data always having 0xFF
|
| - // in the alpha slot (which Skia wants), so we have to ram it in
|
| - // ourselves.
|
| - force_opaque(bm);
|
| - break;
|
| - default:
|
| - // we don't know if we're opaque or not, so compute it.
|
| - if (SkBitmap::ComputeIsOpaque(*bm)) {
|
| - bm->setAlphaType(kOpaque_SkAlphaType);
|
| - }
|
| - }
|
| - if (!bm->isOpaque() && this->getRequireUnpremultipliedColors()) {
|
| - // CGBitmapContext does not support unpremultiplied, so the image has been premultiplied.
|
| - // Convert to unpremultiplied.
|
| - for (int i = 0; i < width; ++i) {
|
| - for (int j = 0; j < height; ++j) {
|
| - uint32_t* addr = bm->getAddr32(i, j);
|
| - *addr = SkUnPreMultiply::UnPreMultiplyPreservingByteOrder(*addr);
|
| - }
|
| - }
|
| - bm->setAlphaType(kUnpremul_SkAlphaType);
|
| - }
|
| - return kSuccess;
|
| -}
|
| -
|
| -///////////////////////////////////////////////////////////////////////////////
|
| -
|
| -extern SkImageDecoder* image_decoder_from_stream(SkStreamRewindable*);
|
| -
|
| -SkImageDecoder* SkImageDecoder::Factory(SkStreamRewindable* stream) {
|
| - SkImageDecoder* decoder = image_decoder_from_stream(stream);
|
| - if (nullptr == decoder) {
|
| - // If no image decoder specific to the stream exists, use SkImageDecoder_CG.
|
| - return new SkImageDecoder_CG;
|
| - } else {
|
| - return decoder;
|
| - }
|
| -}
|
| -
|
| /////////////////////////////////////////////////////////////////////////
|
|
|
| SkMovie* SkMovie::DecodeStream(SkStreamRewindable* stream) {
|
| @@ -355,57 +150,13 @@ static SkImageEncoder* sk_imageencoder_cg_factory(SkImageEncoder::Type t) {
|
|
|
| static SkImageEncoder_EncodeReg gEReg(sk_imageencoder_cg_factory);
|
|
|
| -#ifdef SK_BUILD_FOR_IOS
|
| -class SkPNGImageEncoder_IOS : public SkImageEncoder_CG {
|
| +class SkPNGImageEncoder_CG : public SkImageEncoder_CG {
|
| public:
|
| - SkPNGImageEncoder_IOS()
|
| + SkPNGImageEncoder_CG()
|
| : SkImageEncoder_CG(kPNG_Type) {
|
| }
|
| };
|
|
|
| -DEFINE_ENCODER_CREATOR(PNGImageEncoder_IOS);
|
| -#endif
|
| -
|
| -struct FormatConversion {
|
| - CFStringRef fUTType;
|
| - SkImageDecoder::Format fFormat;
|
| -};
|
| -
|
| -// Array of the types supported by the decoder.
|
| -static const FormatConversion gFormatConversions[] = {
|
| - { kUTTypeBMP, SkImageDecoder::kBMP_Format },
|
| - { kUTTypeGIF, SkImageDecoder::kGIF_Format },
|
| - { kUTTypeICO, SkImageDecoder::kICO_Format },
|
| - { kUTTypeJPEG, SkImageDecoder::kJPEG_Format },
|
| - // Also include JPEG2000
|
| - { kUTTypeJPEG2000, SkImageDecoder::kJPEG_Format },
|
| - { kUTTypePNG, SkImageDecoder::kPNG_Format },
|
| -};
|
| -
|
| -static SkImageDecoder::Format UTType_to_Format(const CFStringRef uttype) {
|
| - for (size_t i = 0; i < SK_ARRAY_COUNT(gFormatConversions); i++) {
|
| - if (CFStringCompare(uttype, gFormatConversions[i].fUTType, 0) == kCFCompareEqualTo) {
|
| - return gFormatConversions[i].fFormat;
|
| - }
|
| - }
|
| - return SkImageDecoder::kUnknown_Format;
|
| -}
|
| -
|
| -static SkImageDecoder::Format get_format_cg(SkStreamRewindable* stream) {
|
| - CGImageSourceRef imageSrc = SkStreamToCGImageSource(stream);
|
| -
|
| - if (nullptr == imageSrc) {
|
| - return SkImageDecoder::kUnknown_Format;
|
| - }
|
| -
|
| - SkAutoTCallVProc<const void, CFRelease> arsrc(imageSrc);
|
| - const CFStringRef name = CGImageSourceGetType(imageSrc);
|
| - if (nullptr == name) {
|
| - return SkImageDecoder::kUnknown_Format;
|
| - }
|
| - return UTType_to_Format(name);
|
| -}
|
| -
|
| -static SkImageDecoder_FormatReg gFormatReg(get_format_cg);
|
| +DEFINE_ENCODER_CREATOR(PNGImageEncoder_CG);
|
|
|
| #endif//defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
|
|
|