Home | History | Annotate | Download | only in ports
      1 /*
      2  * Copyright 2016 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkImageGeneratorCG.h"
      9 
     10 #ifdef SK_BUILD_FOR_MAC
     11 #include <ApplicationServices/ApplicationServices.h>
     12 #endif
     13 
     14 #ifdef SK_BUILD_FOR_IOS
     15 #include <CoreGraphics/CoreGraphics.h>
     16 #include <ImageIO/ImageIO.h>
     17 #include <MobileCoreServices/MobileCoreServices.h>
     18 #endif
     19 
     20 static CGImageSourceRef data_to_CGImageSrc(SkData* data) {
     21     CGDataProviderRef cgData = CGDataProviderCreateWithData(data, data->data(), data->size(),
     22             nullptr);
     23     if (!cgData) {
     24         return nullptr;
     25     }
     26     CGImageSourceRef imageSrc = CGImageSourceCreateWithDataProvider(cgData, 0);
     27     CGDataProviderRelease(cgData);
     28     return imageSrc;
     29 }
     30 
     31 SkImageGenerator* SkImageGeneratorCG::NewFromEncodedCG(SkData* data) {
     32     CGImageSourceRef imageSrc = data_to_CGImageSrc(data);
     33     if (!imageSrc) {
     34         return nullptr;
     35     }
     36 
     37     // Make sure we call CFRelease to free the imageSrc.  Since CFRelease actually takes
     38     // a const void*, we must cast the imageSrc to a const void*.
     39     SkAutoTCallVProc<const void, CFRelease> autoImageSrc(imageSrc);
     40 
     41     CFDictionaryRef properties = CGImageSourceCopyPropertiesAtIndex(imageSrc, 0, nullptr);
     42     if (!properties) {
     43         return nullptr;
     44     }
     45 
     46     CFNumberRef widthRef = (CFNumberRef) (CFDictionaryGetValue(properties,
     47             kCGImagePropertyPixelWidth));
     48     CFNumberRef heightRef = (CFNumberRef) (CFDictionaryGetValue(properties,
     49             kCGImagePropertyPixelHeight));
     50     if (nullptr == widthRef || nullptr == heightRef) {
     51         return nullptr;
     52     }
     53     bool hasAlpha = (bool) (CFDictionaryGetValue(properties,
     54             kCGImagePropertyHasAlpha));
     55 
     56     int width, height;
     57     if (!CFNumberGetValue(widthRef, kCFNumberIntType, &width) ||
     58             !CFNumberGetValue(heightRef, kCFNumberIntType, &height)) {
     59         return nullptr;
     60     }
     61 
     62     SkAlphaType alphaType = hasAlpha ? kPremul_SkAlphaType : kOpaque_SkAlphaType;
     63     SkImageInfo info = SkImageInfo::MakeS32(width, height, alphaType);
     64 
     65     // FIXME: We have the opportunity to extract color space information here,
     66     //        though I think it makes sense to wait until we understand how
     67     //        we want to communicate it to the generator.
     68 
     69     return new SkImageGeneratorCG(info, autoImageSrc.release(), data);
     70 }
     71 
     72 SkImageGeneratorCG::SkImageGeneratorCG(const SkImageInfo& info, const void* imageSrc, SkData* data)
     73     : INHERITED(info)
     74     , fImageSrc(imageSrc)
     75     , fData(SkRef(data))
     76 {}
     77 
     78 SkData* SkImageGeneratorCG::onRefEncodedData() {
     79     return SkRef(fData.get());
     80 }
     81 
     82 bool SkImageGeneratorCG::onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
     83         const Options&) {
     84     if (kN32_SkColorType != info.colorType()) {
     85         // FIXME: Support other colorTypes.
     86         return false;
     87     }
     88 
     89     switch (info.alphaType()) {
     90         case kOpaque_SkAlphaType:
     91             if (kOpaque_SkAlphaType != this->getInfo().alphaType()) {
     92                 return false;
     93             }
     94             break;
     95         case kPremul_SkAlphaType:
     96             break;
     97         default:
     98             return false;
     99     }
    100 
    101     CGImageRef image = CGImageSourceCreateImageAtIndex((CGImageSourceRef) fImageSrc.get(), 0,
    102             nullptr);
    103     if (!image) {
    104         return false;
    105     }
    106     SkAutoTCallVProc<CGImage, CGImageRelease> autoImage(image);
    107 
    108     // FIXME: Using this function (as opposed to swizzling ourselves) greatly
    109     //        restricts the color and alpha types that we support.  If we
    110     //        swizzle ourselves, we can add support for:
    111     //            kUnpremul_SkAlphaType
    112     //            16-bit per component RGBA
    113     //            kGray_8_SkColorType
    114     //            kIndex_8_SkColorType
    115     //        Additionally, it would be interesting to compare the performance
    116     //        of SkSwizzler with CG's built in swizzler.
    117     if (!SkCopyPixelsFromCGImage(info, rowBytes, pixels, image)) {
    118         return false;
    119     }
    120 
    121     return true;
    122 }
    123