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