blob: a99513135d9e0f978a956168482c6632357f3ae6 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
reed@android.com6efdc472008-12-19 18:24:35 +00008#include "SkBitmap.h"
9#include "SkColorPriv.h"
10#include "SkMath.h"
11
12#if defined(SK_BUILD_FOR_MAC) && !defined(SK_USE_WXWIDGETS)
13
14#include <ApplicationServices/ApplicationServices.h>
15
16#ifndef __ppc__
17 #define SWAP_16BIT
18#endif
19
20static void convertGL32_to_Mac32(uint32_t dst[], const SkBitmap& bm) {
21 memcpy(dst, bm.getPixels(), bm.getSize());
22 return;
23
24 uint32_t* stop = dst + (bm.getSize() >> 2);
25 const uint8_t* src = (const uint8_t*)bm.getPixels();
26 while (dst < stop) {
27 *dst++ = src[2] << 24 | src[1] << 16 | src[0] << 8 | src[3] << 0;
28 src += sizeof(uint32_t);
29 }
30}
31
32static void convert565_to_32(uint32_t dst[], const SkBitmap& bm) {
33 for (int y = 0; y < bm.height(); y++) {
34 const uint16_t* src = bm.getAddr16(0, y);
35 const uint16_t* stop = src + bm.width();
36 while (src < stop) {
37 unsigned c = *src++;
38 unsigned r = SkPacked16ToR32(c);
39 unsigned g = SkPacked16ToG32(c);
40 unsigned b = SkPacked16ToB32(c);
41
42 *dst++ = (b << 24) | (g << 16) | (r << 8) | 0xFF;
43 }
44 }
45}
46
47static void convert4444_to_555(uint16_t dst[], const uint16_t src[], int count)
48{
49 const uint16_t* stop = src + count;
50
51 while (src < stop)
52 {
53 unsigned c = *src++;
54
55 unsigned r = SkGetPackedR4444(c);
56 unsigned g = SkGetPackedG4444(c);
57 unsigned b = SkGetPackedB4444(c);
58 // convert to 5 bits
59 r = (r << 1) | (r >> 3);
60 g = (g << 1) | (g >> 3);
61 b = (b << 1) | (b >> 3);
62 // build the 555
63 c = (r << 10) | (g << 5) | b;
64
65#ifdef SWAP_16BIT
66 c = (c >> 8) | (c << 8);
67#endif
68 *dst++ = c;
69 }
70}
71
72#include "SkTemplates.h"
73
74static CGImageRef bitmap2imageref(const SkBitmap& bm) {
75 size_t bitsPerComp;
76 size_t bitsPerPixel;
77 CGBitmapInfo info;
78 CGColorSpaceRef cs = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
79 CGDataProviderRef data = CGDataProviderCreateWithData(NULL,
80 bm.getPixels(),
81 bm.getSize(),
82 NULL);
83 SkAutoTCallVProc<CGDataProvider, CGDataProviderRelease> acp(data);
84 SkAutoTCallVProc<CGColorSpace, CGColorSpaceRelease> acp2(cs);
85
86 switch (bm.config()) {
87 case SkBitmap::kARGB_8888_Config:
88 bitsPerComp = 8;
89 bitsPerPixel = 32;
90 info = kCGImageAlphaPremultipliedLast;
91 break;
92 case SkBitmap::kARGB_4444_Config:
93 bitsPerComp = 4;
94 bitsPerPixel = 16;
95 info = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder16Little;
96 break;
97#if 0 // not supported by quartz !!!
98 case SkBitmap::kRGB_565_Config:
99 bitsPerComp = 5;
100 bitsPerPixel = 16;
101 info = kCGImageAlphaNone | kCGBitmapByteOrder16Little;
102 break;
103#endif
104 default:
105 return NULL;
106 }
107
108 return CGImageCreate(bm.width(), bm.height(), bitsPerComp, bitsPerPixel,
109 bm.rowBytes(), cs, info, data,
110 NULL, false, kCGRenderingIntentDefault);
111}
112
113void SkBitmap::drawToPort(WindowRef wind, CGContextRef cg) const {
114 if (fPixels == NULL || fWidth == 0 || fHeight == 0) {
115 return;
116 }
117
118 bool useQD = false;
119 if (NULL == cg) {
120 SetPortWindowPort(wind);
121 QDBeginCGContext(GetWindowPort(wind), &cg);
122 useQD = true;
123 }
124
125 SkBitmap bm;
126 if (this->config() == kRGB_565_Config) {
127 this->copyTo(&bm, kARGB_8888_Config);
128 } else {
129 bm = *this;
130 }
131 bm.lockPixels();
132
133 CGImageRef image = bitmap2imageref(bm);
134 if (image) {
135 CGRect rect;
136 rect.origin.x = rect.origin.y = 0;
137 rect.size.width = bm.width();
138 rect.size.height = bm.height();
139
140 CGContextDrawImage(cg, rect, image);
141 CGImageRelease(image);
142 }
143
144 if (useQD) {
145 QDEndCGContext(GetWindowPort(wind), &cg);
146 }
147}
148
149#endif