Home | History | Annotate | Download | only in mac
      1 #include "SkCGUtils.h"
      2 #include "SkBitmap.h"
      3 #include "SkColorPriv.h"
      4 
      5 extern CGImageRef SkCreateCGImageRef(const SkBitmap&);
      6 
      7 static void SkBitmap_ReleaseInfo(void* info, const void* pixelData, size_t size) {
      8     SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(info);
      9     delete bitmap;
     10 }
     11 
     12 #define HAS_ARGB_SHIFTS(a, r, g, b) \
     13     (SK_A32_SHIFT == (a) && SK_R32_SHIFT == (r) \
     14     && SK_G32_SHIFT == (g) && SK_B32_SHIFT == (b))
     15 
     16 static SkBitmap* prepareForImageRef(const SkBitmap& bm,
     17                                     size_t* bitsPerComponent,
     18                                     CGBitmapInfo* info) {
     19     bool upscaleTo32 = false;
     20 
     21     switch (bm.config()) {
     22         case SkBitmap::kRGB_565_Config:
     23             upscaleTo32 = true;
     24             // fall through
     25         case SkBitmap::kARGB_8888_Config:
     26             *bitsPerComponent = 8;
     27 #if defined(SK_CPU_LENDIAN) && HAS_ARGB_SHIFTS(24, 0, 8, 16) \
     28  || defined(SK_CPU_BENDIAN) && HAS_ARGB_SHIFTS(0, 24, 16, 8)
     29             *info = kCGBitmapByteOrder32Big |
     30                     kCGImageAlphaPremultipliedLast;
     31 #elif defined(SK_CPU_LENDIAN) && HAS_ARGB_SHIFTS(24, 16, 8, 0) \
     32    || defined(SK_CPU_BENDIAN) && HAS_ARGB_SHIFTS(24, 16, 8, 0)
     33             // Matches the CGBitmapInfo that Apple recommends for best
     34             // performance, used by google chrome.
     35             *info = kCGBitmapByteOrder32Host |
     36                     kCGImageAlphaPremultipliedFirst;
     37 #else
     38 // ...add more formats as required...
     39 #warning Cannot convert SkBitmap to CGImageRef with these shiftmasks. \
     40             This will probably not work.
     41             // Legacy behavior. Perhaps turn this into an error at some
     42             // point.
     43             *info = kCGBitmapByteOrder32Big |
     44                     kCGImageAlphaPremultipliedLast;
     45 #endif
     46             break;
     47 #if 0
     48         case SkBitmap::kRGB_565_Config:
     49             // doesn't see quite right. Are they thinking 1555?
     50             *bitsPerComponent = 5;
     51             *info = kCGBitmapByteOrder16Little;
     52             break;
     53 #endif
     54         case SkBitmap::kARGB_4444_Config:
     55             *bitsPerComponent = 4;
     56             *info = kCGBitmapByteOrder16Little | kCGImageAlphaPremultipliedLast;
     57             break;
     58         default:
     59             return NULL;
     60     }
     61 
     62     SkBitmap* copy;
     63     if (upscaleTo32) {
     64         copy = new SkBitmap;
     65         // here we make a ceep copy of the pixels, since CG won't take our
     66         // 565 directly
     67         bm.copyTo(copy, SkBitmap::kARGB_8888_Config);
     68     } else {
     69         copy = new SkBitmap(bm);
     70     }
     71     return copy;
     72 }
     73 
     74 #undef HAS_ARGB_SHIFTS
     75 
     76 CGImageRef SkCreateCGImageRef(const SkBitmap& bm) {
     77     size_t bitsPerComponent;
     78     CGBitmapInfo info;
     79 
     80     SkBitmap* bitmap = prepareForImageRef(bm, &bitsPerComponent, &info);
     81     if (NULL == bitmap) {
     82         return NULL;
     83     }
     84 
     85     const int w = bitmap->width();
     86     const int h = bitmap->height();
     87     const size_t s = bitmap->getSize();
     88 
     89     // our provider "owns" the bitmap*, and will take care of deleting it
     90 	// we initially lock it, so we can access the pixels. The bitmap will be deleted in the release
     91 	// proc, which will in turn unlock the pixels
     92 	bitmap->lockPixels();
     93     CGDataProviderRef dataRef = CGDataProviderCreateWithData(bitmap, bitmap->getPixels(), s,
     94 															 SkBitmap_ReleaseInfo);
     95 
     96     CGColorSpaceRef space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
     97     CGImageRef ref = CGImageCreate(w, h, bitsPerComponent,
     98                                    bitmap->bytesPerPixel() * 8,
     99                                    bitmap->rowBytes(), space, info, dataRef,
    100                                    NULL, false, kCGRenderingIntentDefault);
    101     CGColorSpaceRelease(space);
    102     CGDataProviderRelease(dataRef);
    103     return ref;
    104 }
    105 
    106 
    107