• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "SkCGUtils.h"
2 #include "SkBitmap.h"
3 #include "SkColorPriv.h"
4 
5 extern CGImageRef SkCreateCGImageRef(const SkBitmap&);
6 
SkBitmap_ReleaseInfo(void * info,const void * pixelData,size_t size)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 
prepareForImageRef(const SkBitmap & bm,size_t * bitsPerComponent,CGBitmapInfo * info)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 
SkCreateCGImageRef(const SkBitmap & bm)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