1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
71ee76510f5dbf632d30975fc3509ef4f609156d2mtklein
81ee76510f5dbf632d30975fc3509ef4f609156d2mtklein#include "SkTypes.h"
91ee76510f5dbf632d30975fc3509ef4f609156d2mtklein#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
101ee76510f5dbf632d30975fc3509ef4f609156d2mtklein
110d55f1e73cbbf5456fb05108a0db1f33dafdae79reed@android.com#include "SkCGUtils.h"
12758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com#include "SkBitmap.h"
13a545a5598e59c22c529e5f33964df1ddd6601ac2reed@android.com#include "SkColorPriv.h"
14758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com
1560b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.orgstatic CGBitmapInfo ComputeCGAlphaInfo_RGBA(SkAlphaType at) {
1660b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    CGBitmapInfo info = kCGBitmapByteOrder32Big;
1760b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    switch (at) {
1844977485bdac75c055c3fa638f118874ccd2d22freed        case kUnknown_SkAlphaType:
1944977485bdac75c055c3fa638f118874ccd2d22freed            break;
2060b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        case kOpaque_SkAlphaType:
2160b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            info |= kCGImageAlphaNoneSkipLast;
2260b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            break;
2360b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        case kPremul_SkAlphaType:
2460b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            info |= kCGImageAlphaPremultipliedLast;
2560b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            break;
2660b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        case kUnpremul_SkAlphaType:
2760b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            info |= kCGImageAlphaLast;
2860b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            break;
2960b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    }
3060b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    return info;
3160b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org}
3260b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org
3360b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.orgstatic CGBitmapInfo ComputeCGAlphaInfo_BGRA(SkAlphaType at) {
3460b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    CGBitmapInfo info = kCGBitmapByteOrder32Little;
3560b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    switch (at) {
3644977485bdac75c055c3fa638f118874ccd2d22freed        case kUnknown_SkAlphaType:
3744977485bdac75c055c3fa638f118874ccd2d22freed            break;
3860b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        case kOpaque_SkAlphaType:
3960b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            info |= kCGImageAlphaNoneSkipFirst;
4060b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            break;
4160b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        case kPremul_SkAlphaType:
4260b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            info |= kCGImageAlphaPremultipliedFirst;
4360b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            break;
4460b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        case kUnpremul_SkAlphaType:
4560b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            info |= kCGImageAlphaFirst;
4660b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            break;
4760b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    }
4860b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    return info;
4960b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org}
5060b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org
512b26cac4fd1a0ff6bfc84757f35198afba3ee1d2reed@android.comstatic void SkBitmap_ReleaseInfo(void* info, const void* pixelData, size_t size) {
52758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(info);
53758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    delete bitmap;
54758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com}
55758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com
56d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.comstatic bool getBitmapInfo(const SkBitmap& bm,
579c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com                          size_t* bitsPerComponent,
589c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com                          CGBitmapInfo* info,
599c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com                          bool* upscaleTo32) {
609c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com    if (upscaleTo32) {
619c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com        *upscaleTo32 = false;
629c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com    }
63d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
64e24ad23ae67ffcb0dc545b7e426cf08d102e0868commit-bot@chromium.org    switch (bm.colorType()) {
65e24ad23ae67ffcb0dc545b7e426cf08d102e0868commit-bot@chromium.org        case kRGB_565_SkColorType:
66e24ad23ae67ffcb0dc545b7e426cf08d102e0868commit-bot@chromium.org#if 0
67e24ad23ae67ffcb0dc545b7e426cf08d102e0868commit-bot@chromium.org            // doesn't see quite right. Are they thinking 1555?
68e24ad23ae67ffcb0dc545b7e426cf08d102e0868commit-bot@chromium.org            *bitsPerComponent = 5;
69e24ad23ae67ffcb0dc545b7e426cf08d102e0868commit-bot@chromium.org            *info = kCGBitmapByteOrder16Little | kCGImageAlphaNone;
7060b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org#else
719c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com            if (upscaleTo32) {
729c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com                *upscaleTo32 = true;
739c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com            }
7460b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            // now treat like RGBA
75758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com            *bitsPerComponent = 8;
7660b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            *info = ComputeCGAlphaInfo_RGBA(kOpaque_SkAlphaType);
778ede49268daa98c4b2bce1c379aeb592f96243eereed@android.com#endif
78758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com            break;
7960b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        case kRGBA_8888_SkColorType:
8060b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            *bitsPerComponent = 8;
8160b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            *info = ComputeCGAlphaInfo_RGBA(bm.alphaType());
8260b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            break;
8360b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        case kBGRA_8888_SkColorType:
8460b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            *bitsPerComponent = 8;
8560b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            *info = ComputeCGAlphaInfo_BGRA(bm.alphaType());
8660b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            break;
87e24ad23ae67ffcb0dc545b7e426cf08d102e0868commit-bot@chromium.org        case kARGB_4444_SkColorType:
880680d6c7caa9c2d4b1e5ee49e5816b96be0cc7bfreed@android.com            *bitsPerComponent = 4;
89426648ef313dff7030249f99dcd7bc8badcbe054scroggo@google.com            *info = kCGBitmapByteOrder16Little;
90426648ef313dff7030249f99dcd7bc8badcbe054scroggo@google.com            if (bm.isOpaque()) {
91426648ef313dff7030249f99dcd7bc8badcbe054scroggo@google.com                *info |= kCGImageAlphaNoneSkipLast;
92426648ef313dff7030249f99dcd7bc8badcbe054scroggo@google.com            } else {
93426648ef313dff7030249f99dcd7bc8badcbe054scroggo@google.com                *info |= kCGImageAlphaPremultipliedLast;
94426648ef313dff7030249f99dcd7bc8badcbe054scroggo@google.com            }
950680d6c7caa9c2d4b1e5ee49e5816b96be0cc7bfreed@android.com            break;
96758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com        default:
979c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com            return false;
989c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com    }
999c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com    return true;
1009c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com}
1019c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com
1029c16bc020f1e8991e2068760fe49521a94ded3efreed@google.comstatic SkBitmap* prepareForImageRef(const SkBitmap& bm,
1039c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com                                    size_t* bitsPerComponent,
1049c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com                                    CGBitmapInfo* info) {
1059c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com    bool upscaleTo32;
1069c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com    if (!getBitmapInfo(bm, bitsPerComponent, info, &upscaleTo32)) {
10796fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
108758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    }
109758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com
11032a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com    SkBitmap* copy;
11132a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com    if (upscaleTo32) {
11232a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com        copy = new SkBitmap;
11332a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com        // here we make a ceep copy of the pixels, since CG won't take our
11432a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com        // 565 directly
11528fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org        bm.copyTo(copy, kN32_SkColorType);
11632a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com    } else {
11732a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com        copy = new SkBitmap(bm);
11832a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com    }
11932a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com    return copy;
120758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com}
121758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com
12238669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.comCGImageRef SkCreateCGImageRefWithColorspace(const SkBitmap& bm,
12338669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com                                            CGColorSpaceRef colorSpace) {
12438669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com    size_t bitsPerComponent SK_INIT_TO_AVOID_WARNING;
12538669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com    CGBitmapInfo info       SK_INIT_TO_AVOID_WARNING;
126758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com
127758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    SkBitmap* bitmap = prepareForImageRef(bm, &bitsPerComponent, &info);
12896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == bitmap) {
12996fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
130758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    }
131758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com
132758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    const int w = bitmap->width();
133758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    const int h = bitmap->height();
134758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    const size_t s = bitmap->getSize();
135758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com
136758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    // our provider "owns" the bitmap*, and will take care of deleting it
137d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com    // we initially lock it, so we can access the pixels. The bitmap will be deleted in the release
138d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com    // proc, which will in turn unlock the pixels
139d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com    bitmap->lockPixels();
1402b26cac4fd1a0ff6bfc84757f35198afba3ee1d2reed@android.com    CGDataProviderRef dataRef = CGDataProviderCreateWithData(bitmap, bitmap->getPixels(), s,
141d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com                                                             SkBitmap_ReleaseInfo);
1422b26cac4fd1a0ff6bfc84757f35198afba3ee1d2reed@android.com
14338669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com    bool releaseColorSpace = false;
14496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == colorSpace) {
145c280d112a820fce69bf6bac4dafdbb99d84077e9reed@google.com        colorSpace = CGColorSpaceCreateDeviceRGB();
14638669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com        releaseColorSpace = true;
14738669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com    }
14838669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com
149758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    CGImageRef ref = CGImageCreate(w, h, bitsPerComponent,
150758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com                                   bitmap->bytesPerPixel() * 8,
15138669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com                                   bitmap->rowBytes(), colorSpace, info, dataRef,
15296fcdcc219d2a0d3579719b84b28bede76efba64halcanary                                   nullptr, false, kCGRenderingIntentDefault);
15338669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com
15438669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com    if (releaseColorSpace) {
15538669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com        CGColorSpaceRelease(colorSpace);
15638669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com    }
157758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    CGDataProviderRelease(dataRef);
158758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    return ref;
159758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com}
160758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com
161f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comvoid SkCGDrawBitmap(CGContextRef cg, const SkBitmap& bm, float x, float y) {
162f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    CGImageRef img = SkCreateCGImageRef(bm);
163f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
164f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    if (img) {
165f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        CGRect r = CGRectMake(0, 0, bm.width(), bm.height());
16662f465940d57139dfd83e2aef67081017a232417reed@google.com
167f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        CGContextSaveGState(cg);
168f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        CGContextTranslateCTM(cg, x, r.size.height + y);
169f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        CGContextScaleCTM(cg, 1, -1);
17062f465940d57139dfd83e2aef67081017a232417reed@google.com
171f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        CGContextDrawImage(cg, r, img);
17262f465940d57139dfd83e2aef67081017a232417reed@google.com
173f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        CGContextRestoreGState(cg);
17462f465940d57139dfd83e2aef67081017a232417reed@google.com
175f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        CGImageRelease(img);
176f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
177f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com}
178f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
17960b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////////////////////////
18060b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org
181356f7c2600ef54237fb8678cf63d5953f065b7daMike ReedCGContextRef SkCreateCGContext(const SkPixmap& pmap) {
182356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    CGBitmapInfo cg_bitmap_info = 0;
183356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    size_t bitsPerComponent = 0;
184356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    switch (pmap.colorType()) {
185356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        case kRGBA_8888_SkColorType:
186356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed            bitsPerComponent = 8;
187356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed            cg_bitmap_info = ComputeCGAlphaInfo_RGBA(pmap.alphaType());
188356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed            break;
189356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        case kBGRA_8888_SkColorType:
190356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed            bitsPerComponent = 8;
191356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed            cg_bitmap_info = ComputeCGAlphaInfo_BGRA(pmap.alphaType());
192356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed            break;
193356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed        default:
194356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed            return nullptr;   // no other colortypes are supported (for now)
195356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    }
196356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
197356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    size_t rb = pmap.addr() ? pmap.rowBytes() : 0;
198356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
199356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    CGContextRef cg = CGBitmapContextCreate(pmap.writable_addr(), pmap.width(), pmap.height(),
200356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed                                            bitsPerComponent, rb, cs, cg_bitmap_info);
201356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    CFRelease(cs);
202356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed    return cg;
203356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed}
204356f7c2600ef54237fb8678cf63d5953f065b7daMike Reed
20560b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.orgSK_API bool SkCopyPixelsFromCGImage(const SkImageInfo& info, size_t rowBytes, void* pixels,
20660b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org                                    CGImageRef image) {
20760b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    CGBitmapInfo cg_bitmap_info = 0;
20860b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    size_t bitsPerComponent = 0;
20960b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    switch (info.colorType()) {
21060b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        case kRGBA_8888_SkColorType:
21160b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            bitsPerComponent = 8;
21260b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            cg_bitmap_info = ComputeCGAlphaInfo_RGBA(info.alphaType());
21360b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            break;
21460b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        case kBGRA_8888_SkColorType:
21560b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            bitsPerComponent = 8;
21660b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            cg_bitmap_info = ComputeCGAlphaInfo_BGRA(info.alphaType());
21760b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            break;
21860b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        default:
21960b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            return false;   // no other colortypes are supported (for now)
22060b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    }
22160b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org
22260b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
22360b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    CGContextRef cg = CGBitmapContextCreate(pixels, info.width(), info.height(), bitsPerComponent,
22460b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org                                            rowBytes, cs, cg_bitmap_info);
22560b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    CFRelease(cs);
22696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == cg) {
22760b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        return false;
22860b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    }
22960b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org
23060b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    // use this blend mode, to avoid having to erase the pixels first, and to avoid CG performing
23160b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    // any blending (which could introduce errors and be slower).
23260b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    CGContextSetBlendMode(cg, kCGBlendModeCopy);
23360b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org
23460b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    CGContextDrawImage(cg, CGRectMake(0, 0, info.width(), info.height()), image);
23560b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    CGContextRelease(cg);
23660b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    return true;
23760b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org}
23860b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org
239463c848f3b63b52e3834e405ff11fd1e653ed271Mike Reedbool SkCreateBitmapFromCGImage(SkBitmap* dst, CGImageRef image) {
240463c848f3b63b52e3834e405ff11fd1e653ed271Mike Reed    const int width = SkToInt(CGImageGetWidth(image));
241463c848f3b63b52e3834e405ff11fd1e653ed271Mike Reed    const int height = SkToInt(CGImageGetHeight(image));
24260b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
24360b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org
24460b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    SkBitmap tmp;
245848250415eddc54075f7eb8795e8db79e749c6abreed    if (!tmp.tryAllocPixels(info)) {
24660b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        return false;
24760b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    }
24860b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org
24960b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    if (!SkCopyPixelsFromCGImage(tmp.info(), tmp.rowBytes(), tmp.getPixels(), image)) {
25060b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        return false;
25160b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    }
25260b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org
25360b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    CGImageAlphaInfo cgInfo = CGImageGetAlphaInfo(image);
25460b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    switch (cgInfo) {
25560b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        case kCGImageAlphaNone:
25660b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        case kCGImageAlphaNoneSkipLast:
25760b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        case kCGImageAlphaNoneSkipFirst:
25860b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            SkASSERT(SkBitmap::ComputeIsOpaque(tmp));
25960b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            tmp.setAlphaType(kOpaque_SkAlphaType);
26060b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            break;
26160b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        default:
26260b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            // we don't know if we're opaque or not, so compute it.
26360b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            if (SkBitmap::ComputeIsOpaque(tmp)) {
26460b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org                tmp.setAlphaType(kOpaque_SkAlphaType);
26560b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            }
26660b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    }
26760b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org
26860b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    *dst = tmp;
26960b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    return true;
27060b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org}
2711ee76510f5dbf632d30975fc3509ef4f609156d2mtklein
272463c848f3b63b52e3834e405ff11fd1e653ed271Mike Reedsk_sp<SkImage> SkMakeImageFromCGImage(CGImageRef src) {
273463c848f3b63b52e3834e405ff11fd1e653ed271Mike Reed    SkBitmap bm;
274463c848f3b63b52e3834e405ff11fd1e653ed271Mike Reed    if (!SkCreateBitmapFromCGImage(&bm, src)) {
275463c848f3b63b52e3834e405ff11fd1e653ed271Mike Reed        return nullptr;
276463c848f3b63b52e3834e405ff11fd1e653ed271Mike Reed    }
277463c848f3b63b52e3834e405ff11fd1e653ed271Mike Reed
278463c848f3b63b52e3834e405ff11fd1e653ed271Mike Reed    bm.setImmutable();
279463c848f3b63b52e3834e405ff11fd1e653ed271Mike Reed    return SkImage::MakeFromBitmap(bm);
280463c848f3b63b52e3834e405ff11fd1e653ed271Mike Reed}
281463c848f3b63b52e3834e405ff11fd1e653ed271Mike Reed
2821ee76510f5dbf632d30975fc3509ef4f609156d2mtklein#endif//defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
283