180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/* 280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2011 Google Inc. 380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * 480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be 580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file. 680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkBitmap.h" 980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkColorPriv.h" 1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkMath.h" 1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if defined(SK_BUILD_FOR_MAC) 1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include <ApplicationServices/ApplicationServices.h> 1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifndef __ppc__ 1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define SWAP_16BIT 1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void convertGL32_to_Mac32(uint32_t dst[], const SkBitmap& bm) { 2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru memcpy(dst, bm.getPixels(), bm.getSize()); 2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return; 2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint32_t* stop = dst + (bm.getSize() >> 2); 2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const uint8_t* src = (const uint8_t*)bm.getPixels(); 2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru while (dst < stop) { 2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *dst++ = src[2] << 24 | src[1] << 16 | src[0] << 8 | src[3] << 0; 2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru src += sizeof(uint32_t); 2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void convert565_to_32(uint32_t dst[], const SkBitmap& bm) { 3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru for (int y = 0; y < bm.height(); y++) { 3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const uint16_t* src = bm.getAddr16(0, y); 3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const uint16_t* stop = src + bm.width(); 3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru while (src < stop) { 3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned c = *src++; 3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned r = SkPacked16ToR32(c); 3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned g = SkPacked16ToG32(c); 4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned b = SkPacked16ToB32(c); 4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *dst++ = (b << 24) | (g << 16) | (r << 8) | 0xFF; 4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void convert4444_to_555(uint16_t dst[], const uint16_t src[], int count) 4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{ 4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const uint16_t* stop = src + count; 5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru while (src < stop) 5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru { 5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned c = *src++; 5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned r = SkGetPackedR4444(c); 5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned g = SkGetPackedG4444(c); 5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned b = SkGetPackedB4444(c); 5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // convert to 5 bits 5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru r = (r << 1) | (r >> 3); 6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru g = (g << 1) | (g >> 3); 6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru b = (b << 1) | (b >> 3); 6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // build the 555 6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru c = (r << 10) | (g << 5) | b; 6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SWAP_16BIT 6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru c = (c >> 8) | (c << 8); 6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *dst++ = c; 6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTemplates.h" 7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic CGImageRef bitmap2imageref(const SkBitmap& bm) { 7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru size_t bitsPerComp; 7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru size_t bitsPerPixel; 7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru CGBitmapInfo info; 7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru CGColorSpaceRef cs = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); 7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru CGDataProviderRef data = CGDataProviderCreateWithData(NULL, 8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bm.getPixels(), 8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bm.getSize(), 8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru NULL); 8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkAutoTCallVProc<CGDataProvider, CGDataProviderRelease> acp(data); 8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkAutoTCallVProc<CGColorSpace, CGColorSpaceRelease> acp2(cs); 8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru switch (bm.config()) { 8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case SkBitmap::kARGB_8888_Config: 8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bitsPerComp = 8; 8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bitsPerPixel = 32; 9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru info = kCGImageAlphaPremultipliedLast; 9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru break; 9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case SkBitmap::kARGB_4444_Config: 9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bitsPerComp = 4; 9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bitsPerPixel = 16; 9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru info = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder16Little; 9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru break; 9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if 0 // not supported by quartz !!! 9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case SkBitmap::kRGB_565_Config: 9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bitsPerComp = 5; 10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bitsPerPixel = 16; 10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru info = kCGImageAlphaNone | kCGBitmapByteOrder16Little; 10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru break; 10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru default: 10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return NULL; 10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return CGImageCreate(bm.width(), bm.height(), bitsPerComp, bitsPerPixel, 10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bm.rowBytes(), cs, info, data, 11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru NULL, false, kCGRenderingIntentDefault); 11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkBitmap::drawToPort(WindowRef wind, CGContextRef cg) const { 11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (fPixels == NULL || fWidth == 0 || fHeight == 0) { 11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return; 11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bool useQD = false; 11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (NULL == cg) { 12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SetPortWindowPort(wind); 12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru QDBeginCGContext(GetWindowPort(wind), &cg); 12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru useQD = true; 12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkBitmap bm; 12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (this->config() == kRGB_565_Config) { 12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->copyTo(&bm, kARGB_8888_Config); 12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { 12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bm = *this; 13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bm.lockPixels(); 13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru CGImageRef image = bitmap2imageref(bm); 13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (image) { 13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru CGRect rect; 13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru rect.origin.x = rect.origin.y = 0; 13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru rect.size.width = bm.width(); 13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru rect.size.height = bm.height(); 13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru CGContextDrawImage(cg, rect, image); 14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru CGImageRelease(image); 14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (useQD) { 14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru QDEndCGContext(GetWindowPort(wind), &cg); 14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 150