1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
80d55f1e73cbbf5456fb05108a0db1f33dafdae79reed@android.com#include "SkCGUtils.h"
9758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com#include "SkBitmap.h"
10a545a5598e59c22c529e5f33964df1ddd6601ac2reed@android.com#include "SkColorPriv.h"
11758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com
1260b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.orgstatic CGBitmapInfo ComputeCGAlphaInfo_RGBA(SkAlphaType at) {
1360b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    CGBitmapInfo info = kCGBitmapByteOrder32Big;
1460b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    switch (at) {
1560b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        case kOpaque_SkAlphaType:
1660b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        case kIgnore_SkAlphaType:
1760b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            info |= kCGImageAlphaNoneSkipLast;
1860b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            break;
1960b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        case kPremul_SkAlphaType:
2060b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            info |= kCGImageAlphaPremultipliedLast;
2160b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            break;
2260b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        case kUnpremul_SkAlphaType:
2360b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            info |= kCGImageAlphaLast;
2460b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            break;
2560b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    }
2660b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    return info;
2760b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org}
2860b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org
2960b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.orgstatic CGBitmapInfo ComputeCGAlphaInfo_BGRA(SkAlphaType at) {
3060b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    CGBitmapInfo info = kCGBitmapByteOrder32Little;
3160b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    switch (at) {
3260b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        case kOpaque_SkAlphaType:
3360b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        case kIgnore_SkAlphaType:
3460b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            info |= kCGImageAlphaNoneSkipFirst;
3560b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            break;
3660b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        case kPremul_SkAlphaType:
3760b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            info |= kCGImageAlphaPremultipliedFirst;
3860b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            break;
3960b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        case kUnpremul_SkAlphaType:
4060b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            info |= kCGImageAlphaFirst;
4160b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            break;
4260b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    }
4360b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    return info;
4460b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org}
4560b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org
462b26cac4fd1a0ff6bfc84757f35198afba3ee1d2reed@android.comstatic void SkBitmap_ReleaseInfo(void* info, const void* pixelData, size_t size) {
47758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(info);
48758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    delete bitmap;
49758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com}
50758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com
51d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.comstatic bool getBitmapInfo(const SkBitmap& bm,
529c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com                          size_t* bitsPerComponent,
539c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com                          CGBitmapInfo* info,
549c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com                          bool* upscaleTo32) {
559c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com    if (upscaleTo32) {
569c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com        *upscaleTo32 = false;
579c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com    }
58d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
59e24ad23ae67ffcb0dc545b7e426cf08d102e0868commit-bot@chromium.org    switch (bm.colorType()) {
60e24ad23ae67ffcb0dc545b7e426cf08d102e0868commit-bot@chromium.org        case kRGB_565_SkColorType:
61e24ad23ae67ffcb0dc545b7e426cf08d102e0868commit-bot@chromium.org#if 0
62e24ad23ae67ffcb0dc545b7e426cf08d102e0868commit-bot@chromium.org            // doesn't see quite right. Are they thinking 1555?
63e24ad23ae67ffcb0dc545b7e426cf08d102e0868commit-bot@chromium.org            *bitsPerComponent = 5;
64e24ad23ae67ffcb0dc545b7e426cf08d102e0868commit-bot@chromium.org            *info = kCGBitmapByteOrder16Little | kCGImageAlphaNone;
6560b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org#else
669c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com            if (upscaleTo32) {
679c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com                *upscaleTo32 = true;
689c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com            }
6960b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            // now treat like RGBA
70758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com            *bitsPerComponent = 8;
7160b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            *info = ComputeCGAlphaInfo_RGBA(kOpaque_SkAlphaType);
728ede49268daa98c4b2bce1c379aeb592f96243eereed@android.com#endif
73758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com            break;
7460b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        case kRGBA_8888_SkColorType:
7560b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            *bitsPerComponent = 8;
7660b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            *info = ComputeCGAlphaInfo_RGBA(bm.alphaType());
7760b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            break;
7860b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        case kBGRA_8888_SkColorType:
7960b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            *bitsPerComponent = 8;
8060b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            *info = ComputeCGAlphaInfo_BGRA(bm.alphaType());
8160b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            break;
82e24ad23ae67ffcb0dc545b7e426cf08d102e0868commit-bot@chromium.org        case kARGB_4444_SkColorType:
830680d6c7caa9c2d4b1e5ee49e5816b96be0cc7bfreed@android.com            *bitsPerComponent = 4;
84426648ef313dff7030249f99dcd7bc8badcbe054scroggo@google.com            *info = kCGBitmapByteOrder16Little;
85426648ef313dff7030249f99dcd7bc8badcbe054scroggo@google.com            if (bm.isOpaque()) {
86426648ef313dff7030249f99dcd7bc8badcbe054scroggo@google.com                *info |= kCGImageAlphaNoneSkipLast;
87426648ef313dff7030249f99dcd7bc8badcbe054scroggo@google.com            } else {
88426648ef313dff7030249f99dcd7bc8badcbe054scroggo@google.com                *info |= kCGImageAlphaPremultipliedLast;
89426648ef313dff7030249f99dcd7bc8badcbe054scroggo@google.com            }
900680d6c7caa9c2d4b1e5ee49e5816b96be0cc7bfreed@android.com            break;
91758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com        default:
929c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com            return false;
939c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com    }
949c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com    return true;
959c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com}
969c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com
979c16bc020f1e8991e2068760fe49521a94ded3efreed@google.comstatic SkBitmap* prepareForImageRef(const SkBitmap& bm,
989c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com                                    size_t* bitsPerComponent,
999c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com                                    CGBitmapInfo* info) {
1009c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com    bool upscaleTo32;
1019c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com    if (!getBitmapInfo(bm, bitsPerComponent, info, &upscaleTo32)) {
1029c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com        return NULL;
103758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    }
104758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com
10532a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com    SkBitmap* copy;
10632a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com    if (upscaleTo32) {
10732a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com        copy = new SkBitmap;
10832a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com        // here we make a ceep copy of the pixels, since CG won't take our
10932a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com        // 565 directly
11028fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org        bm.copyTo(copy, kN32_SkColorType);
11132a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com    } else {
11232a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com        copy = new SkBitmap(bm);
11332a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com    }
11432a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com    return copy;
115758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com}
116758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com
11738669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.comCGImageRef SkCreateCGImageRefWithColorspace(const SkBitmap& bm,
11838669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com                                            CGColorSpaceRef colorSpace) {
11938669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com    size_t bitsPerComponent SK_INIT_TO_AVOID_WARNING;
12038669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com    CGBitmapInfo info       SK_INIT_TO_AVOID_WARNING;
121758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com
122758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    SkBitmap* bitmap = prepareForImageRef(bm, &bitsPerComponent, &info);
123758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    if (NULL == bitmap) {
124758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com        return NULL;
125758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    }
126758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com
127758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    const int w = bitmap->width();
128758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    const int h = bitmap->height();
129758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    const size_t s = bitmap->getSize();
130758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com
131758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    // our provider "owns" the bitmap*, and will take care of deleting it
132d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com    // we initially lock it, so we can access the pixels. The bitmap will be deleted in the release
133d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com    // proc, which will in turn unlock the pixels
134d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com    bitmap->lockPixels();
1352b26cac4fd1a0ff6bfc84757f35198afba3ee1d2reed@android.com    CGDataProviderRef dataRef = CGDataProviderCreateWithData(bitmap, bitmap->getPixels(), s,
136d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com                                                             SkBitmap_ReleaseInfo);
1372b26cac4fd1a0ff6bfc84757f35198afba3ee1d2reed@android.com
13838669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com    bool releaseColorSpace = false;
13938669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com    if (NULL == colorSpace) {
140c280d112a820fce69bf6bac4dafdbb99d84077e9reed@google.com        colorSpace = CGColorSpaceCreateDeviceRGB();
14138669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com        releaseColorSpace = true;
14238669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com    }
14338669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com
144758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    CGImageRef ref = CGImageCreate(w, h, bitsPerComponent,
145758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com                                   bitmap->bytesPerPixel() * 8,
14638669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com                                   bitmap->rowBytes(), colorSpace, info, dataRef,
147758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com                                   NULL, false, kCGRenderingIntentDefault);
14838669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com
14938669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com    if (releaseColorSpace) {
15038669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com        CGColorSpaceRelease(colorSpace);
15138669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com    }
152758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    CGDataProviderRelease(dataRef);
153758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    return ref;
154758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com}
155758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com
156f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comvoid SkCGDrawBitmap(CGContextRef cg, const SkBitmap& bm, float x, float y) {
157f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    CGImageRef img = SkCreateCGImageRef(bm);
158f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
159f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    if (img) {
160f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        CGRect r = CGRectMake(0, 0, bm.width(), bm.height());
16162f465940d57139dfd83e2aef67081017a232417reed@google.com
162f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        CGContextSaveGState(cg);
163f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        CGContextTranslateCTM(cg, x, r.size.height + y);
164f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        CGContextScaleCTM(cg, 1, -1);
16562f465940d57139dfd83e2aef67081017a232417reed@google.com
166f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        CGContextDrawImage(cg, r, img);
16762f465940d57139dfd83e2aef67081017a232417reed@google.com
168f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        CGContextRestoreGState(cg);
16962f465940d57139dfd83e2aef67081017a232417reed@google.com
170f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        CGImageRelease(img);
171f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
172f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com}
173f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
174292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com///////////////////////////////////////////////////////////////////////////////
175f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
176292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com#include "SkStream.h"
177292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com
178292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.comclass SkAutoPDFRelease {
179292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.compublic:
180292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    SkAutoPDFRelease(CGPDFDocumentRef doc) : fDoc(doc) {}
181292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    ~SkAutoPDFRelease() {
182292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com        if (fDoc) {
183292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com            CGPDFDocumentRelease(fDoc);
184292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com        }
185292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    }
186292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.comprivate:
187292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    CGPDFDocumentRef fDoc;
188292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com};
189e61a86cfa00ea393ecc4a71fca94e1d476a37ecccommit-bot@chromium.org#define SkAutoPDFRelease(...) SK_REQUIRE_LOCAL_VAR(SkAutoPDFRelease)
190292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com
191292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.comstatic void CGDataProviderReleaseData_FromMalloc(void*, const void* data,
192292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com                                                 size_t size) {
193292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    sk_free((void*)data);
194292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com}
195292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com
196292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.combool SkPDFDocumentToBitmap(SkStream* stream, SkBitmap* output) {
197292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    size_t size = stream->getLength();
198292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    void* ptr = sk_malloc_throw(size);
199292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    stream->read(ptr, size);
200292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    CGDataProviderRef data = CGDataProviderCreateWithData(NULL, ptr, size,
201292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com                                          CGDataProviderReleaseData_FromMalloc);
202292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    if (NULL == data) {
203292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com        return false;
204292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    }
205d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
206292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    CGPDFDocumentRef pdf = CGPDFDocumentCreateWithProvider(data);
207292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    CGDataProviderRelease(data);
208292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    if (NULL == pdf) {
209292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com        return false;
210292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    }
211292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    SkAutoPDFRelease releaseMe(pdf);
212292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com
213292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    CGPDFPageRef page = CGPDFDocumentGetPage(pdf, 1);
214292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    if (NULL == page) {
215292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com        return false;
216292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    }
217d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
218292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    CGRect bounds = CGPDFPageGetBoxRect(page, kCGPDFMediaBox);
219d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
220292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    int w = (int)CGRectGetWidth(bounds);
221292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    int h = (int)CGRectGetHeight(bounds);
222d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
223292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    SkBitmap bitmap;
2249ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    if (!bitmap.allocPixels(SkImageInfo::MakeN32Premul(w, h))) {
2259ebcac54635cde63110d73ad7c43d70772e7872freed@google.com        return false;
2269ebcac54635cde63110d73ad7c43d70772e7872freed@google.com    }
227292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    bitmap.eraseColor(SK_ColorWHITE);
2289c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com
2299c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com    size_t bitsPerComponent;
2309c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com    CGBitmapInfo info;
231d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com    getBitmapInfo(bitmap, &bitsPerComponent, &info, NULL);
232cd88d7c233f7854e14d5ee8fbf6eedb0e45f2014reed@google.com
233cd88d7c233f7854e14d5ee8fbf6eedb0e45f2014reed@google.com    CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
234cd88d7c233f7854e14d5ee8fbf6eedb0e45f2014reed@google.com    CGContextRef ctx = CGBitmapContextCreate(bitmap.getPixels(), w, h,
235cd88d7c233f7854e14d5ee8fbf6eedb0e45f2014reed@google.com                                             bitsPerComponent, bitmap.rowBytes(),
236cd88d7c233f7854e14d5ee8fbf6eedb0e45f2014reed@google.com                                             cs, info);
237cd88d7c233f7854e14d5ee8fbf6eedb0e45f2014reed@google.com    CGColorSpaceRelease(cs);
238cd88d7c233f7854e14d5ee8fbf6eedb0e45f2014reed@google.com
239292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    if (ctx) {
240292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com        CGContextDrawPDFPage(ctx, page);
241292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com        CGContextRelease(ctx);
242292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    }
243292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com
244292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    output->swap(bitmap);
245292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    return true;
246292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com}
24760b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org
24860b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////////////////////////
24960b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org
25060b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.orgSK_API bool SkCopyPixelsFromCGImage(const SkImageInfo& info, size_t rowBytes, void* pixels,
25160b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org                                    CGImageRef image) {
25260b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    CGBitmapInfo cg_bitmap_info = 0;
25360b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    size_t bitsPerComponent = 0;
25460b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    switch (info.colorType()) {
25560b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        case kRGBA_8888_SkColorType:
25660b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            bitsPerComponent = 8;
25760b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            cg_bitmap_info = ComputeCGAlphaInfo_RGBA(info.alphaType());
25860b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            break;
25960b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        case kBGRA_8888_SkColorType:
26060b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            bitsPerComponent = 8;
26160b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            cg_bitmap_info = ComputeCGAlphaInfo_BGRA(info.alphaType());
26260b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            break;
26360b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        default:
26460b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            return false;   // no other colortypes are supported (for now)
26560b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    }
26660b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org
26760b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
26860b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    CGContextRef cg = CGBitmapContextCreate(pixels, info.width(), info.height(), bitsPerComponent,
26960b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org                                            rowBytes, cs, cg_bitmap_info);
27060b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    CFRelease(cs);
27160b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    if (NULL == cg) {
27260b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        return false;
27360b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    }
27460b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org
27560b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    // use this blend mode, to avoid having to erase the pixels first, and to avoid CG performing
27660b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    // any blending (which could introduce errors and be slower).
27760b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    CGContextSetBlendMode(cg, kCGBlendModeCopy);
27860b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org
27960b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    CGContextDrawImage(cg, CGRectMake(0, 0, info.width(), info.height()), image);
28060b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    CGContextRelease(cg);
28160b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    return true;
28260b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org}
28360b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org
28460b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.orgbool SkCreateBitmapFromCGImage(SkBitmap* dst, CGImageRef image, SkISize* scaleToFit) {
28560b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    const int width = scaleToFit ? scaleToFit->width() : SkToInt(CGImageGetWidth(image));
28660b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    const int height = scaleToFit ? scaleToFit->height() : SkToInt(CGImageGetHeight(image));
28760b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
28860b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org
28960b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    SkBitmap tmp;
29060b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    if (!tmp.allocPixels(info)) {
29160b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        return false;
29260b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    }
29360b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org
29460b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    if (!SkCopyPixelsFromCGImage(tmp.info(), tmp.rowBytes(), tmp.getPixels(), image)) {
29560b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        return false;
29660b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    }
29760b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org
29860b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    CGImageAlphaInfo cgInfo = CGImageGetAlphaInfo(image);
29960b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    switch (cgInfo) {
30060b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        case kCGImageAlphaNone:
30160b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        case kCGImageAlphaNoneSkipLast:
30260b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        case kCGImageAlphaNoneSkipFirst:
30360b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            SkASSERT(SkBitmap::ComputeIsOpaque(tmp));
30460b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            tmp.setAlphaType(kOpaque_SkAlphaType);
30560b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            break;
30660b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org        default:
30760b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            // we don't know if we're opaque or not, so compute it.
30860b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            if (SkBitmap::ComputeIsOpaque(tmp)) {
30960b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org                tmp.setAlphaType(kOpaque_SkAlphaType);
31060b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org            }
31160b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    }
31260b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org
31360b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    *dst = tmp;
31460b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org    return true;
31560b5dce19984a5165f6b2f1d6d477f5e8a940761commit-bot@chromium.org}
316