blob: 151dc9b8f9ba8f1c8278d1ab17923bd96f09f12b [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
2 * Copyright 2011 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 */
tfarina@chromium.orge229e922012-09-27 13:44:57 +00007
reed@android.com6efdc472008-12-19 18:24:35 +00008#include "SkBitmap.h"
9#include "SkColorPriv.h"
10#include "SkMath.h"
11
tfarina@chromium.orge229e922012-09-27 13:44:57 +000012#if defined(SK_BUILD_FOR_MAC)
reed@android.com6efdc472008-12-19 18:24:35 +000013
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;
rmistry@google.comd6176b02012-08-23 18:14:13 +000023
reed@android.com6efdc472008-12-19 18:24:35 +000024 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);
rmistry@google.comd6176b02012-08-23 18:14:13 +000041
reed@android.com6efdc472008-12-19 18:24:35 +000042 *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;
rmistry@google.comd6176b02012-08-23 18:14:13 +000050
reed@android.com6efdc472008-12-19 18:24:35 +000051 while (src < stop)
52 {
53 unsigned c = *src++;
rmistry@google.comd6176b02012-08-23 18:14:13 +000054
reed@android.com6efdc472008-12-19 18:24:35 +000055 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;
rmistry@google.comd6176b02012-08-23 18:14:13 +000064
reed@android.com6efdc472008-12-19 18:24:35 +000065#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 {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000114 if (fPixels == NULL || fWidth == 0 || fHeight == 0) {
115 return;
reed@android.com6efdc472008-12-19 18:24:35 +0000116 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000117
reed@android.com6efdc472008-12-19 18:24:35 +0000118 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();
rmistry@google.comd6176b02012-08-23 18:14:13 +0000139
reed@android.com6efdc472008-12-19 18:24:35 +0000140 CGContextDrawImage(cg, rect, image);
141 CGImageRelease(image);
142 }
143
144 if (useQD) {
145 QDEndCGContext(GetWindowPort(wind), &cg);
146 }
147}
148
149#endif