SkCreateCGImageRef.cpp revision 40443b2371ecc61e04ad496f69919dc1e30036f5
1#include "SkCGUtils.h"
2#include "SkBitmap.h"
3#include "SkColorPriv.h"
4
5extern CGImageRef SkCreateCGImageRef(const SkBitmap&);
6
7static 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
16static SkBitmap* prepareForImageRef(const SkBitmap& bm,
17                                    size_t* bitsPerComponent,
18                                    CGBitmapInfo* info) {
19#if 0
20    SkDebugf("---- %d %d %d %d\n", SK_A32_SHIFT, SK_R32_SHIFT,
21             SK_G32_SHIFT, SK_B32_SHIFT);
22#endif
23
24    switch (bm.config()) {
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        case SkBitmap::kRGB_565_Config:
48            // doesn't see quite right. Are they thinking 1555?
49            *bitsPerComponent = 5;
50            *info = kCGBitmapByteOrder16Little;
51            break;
52        case SkBitmap::kARGB_4444_Config:
53            *bitsPerComponent = 4;
54            *info = kCGBitmapByteOrder16Little | kCGImageAlphaPremultipliedLast;
55            break;
56        default:
57            return NULL;
58    }
59
60    return new SkBitmap(bm);
61}
62
63#undef HAS_ARGB_SHIFTS
64
65CGImageRef SkCreateCGImageRef(const SkBitmap& bm) {
66    size_t bitsPerComponent;
67    CGBitmapInfo info;
68
69    SkBitmap* bitmap = prepareForImageRef(bm, &bitsPerComponent, &info);
70    if (NULL == bitmap) {
71        return NULL;
72    }
73
74    const int w = bitmap->width();
75    const int h = bitmap->height();
76    const size_t s = bitmap->getSize();
77
78    // our provider "owns" the bitmap*, and will take care of deleting it
79	// we initially lock it, so we can access the pixels. The bitmap will be deleted in the release
80	// proc, which will in turn unlock the pixels
81	bitmap->lockPixels();
82    CGDataProviderRef dataRef = CGDataProviderCreateWithData(bitmap, bitmap->getPixels(), s,
83															 SkBitmap_ReleaseInfo);
84
85    CGColorSpaceRef space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
86    CGImageRef ref = CGImageCreate(w, h, bitsPerComponent,
87                                   bitmap->bytesPerPixel() * 8,
88                                   bitmap->rowBytes(), space, info, dataRef,
89                                   NULL, false, kCGRenderingIntentDefault);
90    CGColorSpaceRelease(space);
91    CGDataProviderRelease(dataRef);
92    return ref;
93}
94
95
96