SkCreateCGImageRef.cpp revision ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976e
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
122b26cac4fd1a0ff6bfc84757f35198afba3ee1d2reed@android.comstatic void SkBitmap_ReleaseInfo(void* info, const void* pixelData, size_t size) {
13758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(info);
14758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    delete bitmap;
15758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com}
16758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com
17a545a5598e59c22c529e5f33964df1ddd6601ac2reed@android.com#define HAS_ARGB_SHIFTS(a, r, g, b) \
18a545a5598e59c22c529e5f33964df1ddd6601ac2reed@android.com    (SK_A32_SHIFT == (a) && SK_R32_SHIFT == (r) \
19a545a5598e59c22c529e5f33964df1ddd6601ac2reed@android.com    && SK_G32_SHIFT == (g) && SK_B32_SHIFT == (b))
20a545a5598e59c22c529e5f33964df1ddd6601ac2reed@android.com
219c16bc020f1e8991e2068760fe49521a94ded3efreed@google.comstatic bool getBitmapInfo(const SkBitmap& bm,
229c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com                          size_t* bitsPerComponent,
239c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com                          CGBitmapInfo* info,
249c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com                          bool* upscaleTo32) {
259c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com    if (upscaleTo32) {
269c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com        *upscaleTo32 = false;
279c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com    }
289c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com
29758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    switch (bm.config()) {
3032a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com        case SkBitmap::kRGB_565_Config:
319c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com            if (upscaleTo32) {
329c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com                *upscaleTo32 = true;
339c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com            }
3432a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com            // fall through
35758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com        case SkBitmap::kARGB_8888_Config:
36758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com            *bitsPerComponent = 8;
378ede49268daa98c4b2bce1c379aeb592f96243eereed@android.com#if defined(SK_CPU_LENDIAN) && HAS_ARGB_SHIFTS(24, 0, 8, 16) \
389c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com|| defined(SK_CPU_BENDIAN) && HAS_ARGB_SHIFTS(0, 24, 16, 8)
3962f465940d57139dfd83e2aef67081017a232417reed@google.com            *info = kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast;
408ede49268daa98c4b2bce1c379aeb592f96243eereed@android.com#elif defined(SK_CPU_LENDIAN) && HAS_ARGB_SHIFTS(24, 16, 8, 0) \
419c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com|| defined(SK_CPU_BENDIAN) && HAS_ARGB_SHIFTS(24, 16, 8, 0)
428ede49268daa98c4b2bce1c379aeb592f96243eereed@android.com            // Matches the CGBitmapInfo that Apple recommends for best
438ede49268daa98c4b2bce1c379aeb592f96243eereed@android.com            // performance, used by google chrome.
4462f465940d57139dfd83e2aef67081017a232417reed@google.com            *info = kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst;
458ede49268daa98c4b2bce1c379aeb592f96243eereed@android.com#else
469c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com            // ...add more formats as required...
478ede49268daa98c4b2bce1c379aeb592f96243eereed@android.com#warning Cannot convert SkBitmap to CGImageRef with these shiftmasks. \
489c16bc020f1e8991e2068760fe49521a94ded3efreed@google.comThis will probably not work.
498ede49268daa98c4b2bce1c379aeb592f96243eereed@android.com            // Legacy behavior. Perhaps turn this into an error at some
508ede49268daa98c4b2bce1c379aeb592f96243eereed@android.com            // point.
5162f465940d57139dfd83e2aef67081017a232417reed@google.com            *info = kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast;
528ede49268daa98c4b2bce1c379aeb592f96243eereed@android.com#endif
53758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com            break;
5432a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com#if 0
550680d6c7caa9c2d4b1e5ee49e5816b96be0cc7bfreed@android.com        case SkBitmap::kRGB_565_Config:
560680d6c7caa9c2d4b1e5ee49e5816b96be0cc7bfreed@android.com            // doesn't see quite right. Are they thinking 1555?
570680d6c7caa9c2d4b1e5ee49e5816b96be0cc7bfreed@android.com            *bitsPerComponent = 5;
580680d6c7caa9c2d4b1e5ee49e5816b96be0cc7bfreed@android.com            *info = kCGBitmapByteOrder16Little;
590680d6c7caa9c2d4b1e5ee49e5816b96be0cc7bfreed@android.com            break;
6032a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com#endif
610680d6c7caa9c2d4b1e5ee49e5816b96be0cc7bfreed@android.com        case SkBitmap::kARGB_4444_Config:
620680d6c7caa9c2d4b1e5ee49e5816b96be0cc7bfreed@android.com            *bitsPerComponent = 4;
630680d6c7caa9c2d4b1e5ee49e5816b96be0cc7bfreed@android.com            *info = kCGBitmapByteOrder16Little | kCGImageAlphaPremultipliedLast;
640680d6c7caa9c2d4b1e5ee49e5816b96be0cc7bfreed@android.com            break;
65758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com        default:
669c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com            return false;
679c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com    }
689c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com    return true;
699c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com}
709c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com
719c16bc020f1e8991e2068760fe49521a94ded3efreed@google.comstatic SkBitmap* prepareForImageRef(const SkBitmap& bm,
729c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com                                    size_t* bitsPerComponent,
739c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com                                    CGBitmapInfo* info) {
749c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com    bool upscaleTo32;
759c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com    if (!getBitmapInfo(bm, bitsPerComponent, info, &upscaleTo32)) {
769c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com        return NULL;
77758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    }
78758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com
7932a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com    SkBitmap* copy;
8032a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com    if (upscaleTo32) {
8132a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com        copy = new SkBitmap;
8232a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com        // here we make a ceep copy of the pixels, since CG won't take our
8332a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com        // 565 directly
8432a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com        bm.copyTo(copy, SkBitmap::kARGB_8888_Config);
8532a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com    } else {
8632a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com        copy = new SkBitmap(bm);
8732a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com    }
8832a4249cbd3ebcb448fb0824afe875cdf9036686reed@android.com    return copy;
89758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com}
90758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com
91a545a5598e59c22c529e5f33964df1ddd6601ac2reed@android.com#undef HAS_ARGB_SHIFTS
92a545a5598e59c22c529e5f33964df1ddd6601ac2reed@android.com
9338669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.comCGImageRef SkCreateCGImageRefWithColorspace(const SkBitmap& bm,
9438669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com                                            CGColorSpaceRef colorSpace) {
9538669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com    size_t bitsPerComponent SK_INIT_TO_AVOID_WARNING;
9638669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com    CGBitmapInfo info       SK_INIT_TO_AVOID_WARNING;
97758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com
98758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    SkBitmap* bitmap = prepareForImageRef(bm, &bitsPerComponent, &info);
99758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    if (NULL == bitmap) {
100758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com        return NULL;
101758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    }
102758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com
103758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    const int w = bitmap->width();
104758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    const int h = bitmap->height();
105758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    const size_t s = bitmap->getSize();
106758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com
107758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    // our provider "owns" the bitmap*, and will take care of deleting it
1082b26cac4fd1a0ff6bfc84757f35198afba3ee1d2reed@android.com	// we initially lock it, so we can access the pixels. The bitmap will be deleted in the release
1092b26cac4fd1a0ff6bfc84757f35198afba3ee1d2reed@android.com	// proc, which will in turn unlock the pixels
1102b26cac4fd1a0ff6bfc84757f35198afba3ee1d2reed@android.com	bitmap->lockPixels();
1112b26cac4fd1a0ff6bfc84757f35198afba3ee1d2reed@android.com    CGDataProviderRef dataRef = CGDataProviderCreateWithData(bitmap, bitmap->getPixels(), s,
1122b26cac4fd1a0ff6bfc84757f35198afba3ee1d2reed@android.com															 SkBitmap_ReleaseInfo);
1132b26cac4fd1a0ff6bfc84757f35198afba3ee1d2reed@android.com
11438669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com    bool releaseColorSpace = false;
11538669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com    if (NULL == colorSpace) {
116c280d112a820fce69bf6bac4dafdbb99d84077e9reed@google.com        colorSpace = CGColorSpaceCreateDeviceRGB();
11738669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com        releaseColorSpace = true;
11838669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com    }
11938669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com
120758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    CGImageRef ref = CGImageCreate(w, h, bitsPerComponent,
121758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com                                   bitmap->bytesPerPixel() * 8,
12238669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com                                   bitmap->rowBytes(), colorSpace, info, dataRef,
123758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com                                   NULL, false, kCGRenderingIntentDefault);
12438669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com
12538669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com    if (releaseColorSpace) {
12638669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com        CGColorSpaceRelease(colorSpace);
12738669c12c5ab784d5ad94eb2b26b89becac2ba12reed@android.com    }
128758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    CGDataProviderRelease(dataRef);
129758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com    return ref;
130758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com}
131758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com
132f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comvoid SkCGDrawBitmap(CGContextRef cg, const SkBitmap& bm, float x, float y) {
133f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    CGImageRef img = SkCreateCGImageRef(bm);
134f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
135f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    if (img) {
136f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        CGRect r = CGRectMake(0, 0, bm.width(), bm.height());
13762f465940d57139dfd83e2aef67081017a232417reed@google.com
138f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        CGContextSaveGState(cg);
139f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        CGContextTranslateCTM(cg, x, r.size.height + y);
140f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        CGContextScaleCTM(cg, 1, -1);
14162f465940d57139dfd83e2aef67081017a232417reed@google.com
142f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        CGContextDrawImage(cg, r, img);
14362f465940d57139dfd83e2aef67081017a232417reed@google.com
144f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        CGContextRestoreGState(cg);
14562f465940d57139dfd83e2aef67081017a232417reed@google.com
146f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        CGImageRelease(img);
147f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    }
148f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com}
149f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
150292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com///////////////////////////////////////////////////////////////////////////////
151f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
152292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com#include "SkStream.h"
153292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com
154292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.comclass SkAutoPDFRelease {
155292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.compublic:
156292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    SkAutoPDFRelease(CGPDFDocumentRef doc) : fDoc(doc) {}
157292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    ~SkAutoPDFRelease() {
158292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com        if (fDoc) {
159292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com            CGPDFDocumentRelease(fDoc);
160292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com        }
161292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    }
162292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.comprivate:
163292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    CGPDFDocumentRef fDoc;
164292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com};
165292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com
166292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.comstatic void CGDataProviderReleaseData_FromMalloc(void*, const void* data,
167292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com                                                 size_t size) {
168292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    sk_free((void*)data);
169292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com}
170292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com
171292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.combool SkPDFDocumentToBitmap(SkStream* stream, SkBitmap* output) {
172292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    size_t size = stream->getLength();
173292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    void* ptr = sk_malloc_throw(size);
174292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    stream->read(ptr, size);
175292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    CGDataProviderRef data = CGDataProviderCreateWithData(NULL, ptr, size,
176292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com                                          CGDataProviderReleaseData_FromMalloc);
177292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    if (NULL == data) {
178292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com        return false;
179292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    }
180292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com
181292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    CGPDFDocumentRef pdf = CGPDFDocumentCreateWithProvider(data);
182292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    CGDataProviderRelease(data);
183292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    if (NULL == pdf) {
184292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com        return false;
185292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    }
186292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    SkAutoPDFRelease releaseMe(pdf);
187292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com
188292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    CGPDFPageRef page = CGPDFDocumentGetPage(pdf, 1);
189292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    if (NULL == page) {
190292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com        return false;
191292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    }
192292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com
193292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    CGRect bounds = CGPDFPageGetBoxRect(page, kCGPDFMediaBox);
194292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com
195292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    int w = (int)CGRectGetWidth(bounds);
196292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    int h = (int)CGRectGetHeight(bounds);
1979c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com
198292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    SkBitmap bitmap;
199292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    bitmap.setConfig(SkBitmap::kARGB_8888_Config, w, h);
200292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    bitmap.allocPixels();
201292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    bitmap.eraseColor(SK_ColorWHITE);
2029c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com
2039c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com    size_t bitsPerComponent;
2049c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com    CGBitmapInfo info;
2059c16bc020f1e8991e2068760fe49521a94ded3efreed@google.com    getBitmapInfo(bitmap, &bitsPerComponent, &info, NULL);
206cd88d7c233f7854e14d5ee8fbf6eedb0e45f2014reed@google.com
207cd88d7c233f7854e14d5ee8fbf6eedb0e45f2014reed@google.com    CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
208cd88d7c233f7854e14d5ee8fbf6eedb0e45f2014reed@google.com    CGContextRef ctx = CGBitmapContextCreate(bitmap.getPixels(), w, h,
209cd88d7c233f7854e14d5ee8fbf6eedb0e45f2014reed@google.com                                             bitsPerComponent, bitmap.rowBytes(),
210cd88d7c233f7854e14d5ee8fbf6eedb0e45f2014reed@google.com                                             cs, info);
211cd88d7c233f7854e14d5ee8fbf6eedb0e45f2014reed@google.com    CGColorSpaceRelease(cs);
212cd88d7c233f7854e14d5ee8fbf6eedb0e45f2014reed@google.com
213292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    if (ctx) {
214292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com        CGContextDrawPDFPage(ctx, page);
215292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com        CGContextRelease(ctx);
216292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    }
217292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com
218292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    output->swap(bitmap);
219292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com    return true;
220292ade6625f2f3bed84afbe4d669613ebf3785f9reed@google.com}
221758b129f11d8ce2d2235f73ea4523f21f3d8b079reed@android.com
222