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