Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 #include "SkCGUtils.h" | 8 #include "SkCGUtils.h" |
| 9 #include "SkBitmap.h" | 9 #include "SkBitmap.h" |
| 10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
| 11 | 11 |
| 12 static uint32_t ComputeCGAlphaInfo_RGBA(SkAlphaType at) { | |
|
scroggo
2014/04/22 14:58:17
Should these return CGBitmapInfo for documentation
reed1
2014/04/22 17:51:39
Done.
| |
| 13 uint32_t info = kCGBitmapByteOrder32Big; | |
| 14 switch (at) { | |
| 15 case kOpaque_SkAlphaType: | |
| 16 case kIgnore_SkAlphaType: | |
| 17 info |= kCGImageAlphaNoneSkipLast; | |
| 18 break; | |
| 19 case kPremul_SkAlphaType: | |
| 20 info |= kCGImageAlphaPremultipliedLast; | |
| 21 break; | |
| 22 case kUnpremul_SkAlphaType: | |
| 23 info |= kCGImageAlphaLast; | |
| 24 break; | |
| 25 } | |
| 26 return info; | |
| 27 } | |
| 28 | |
| 29 static uint32_t ComputeCGAlphaInfo_BGRA(SkAlphaType at) { | |
| 30 uint32_t info = kCGBitmapByteOrder32Little; | |
| 31 switch (at) { | |
| 32 case kOpaque_SkAlphaType: | |
| 33 case kIgnore_SkAlphaType: | |
| 34 info |= kCGImageAlphaNoneSkipFirst; | |
| 35 break; | |
| 36 case kPremul_SkAlphaType: | |
| 37 info |= kCGImageAlphaPremultipliedFirst; | |
| 38 break; | |
| 39 case kUnpremul_SkAlphaType: | |
| 40 info |= kCGImageAlphaFirst; | |
| 41 break; | |
| 42 } | |
| 43 return info; | |
| 44 } | |
| 45 | |
| 12 static void SkBitmap_ReleaseInfo(void* info, const void* pixelData, size_t size) { | 46 static void SkBitmap_ReleaseInfo(void* info, const void* pixelData, size_t size) { |
| 13 SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(info); | 47 SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(info); |
| 14 delete bitmap; | 48 delete bitmap; |
| 15 } | 49 } |
| 16 | 50 |
| 17 static bool getBitmapInfo(const SkBitmap& bm, | 51 static bool getBitmapInfo(const SkBitmap& bm, |
| 18 size_t* bitsPerComponent, | 52 size_t* bitsPerComponent, |
| 19 CGBitmapInfo* info, | 53 CGBitmapInfo* info, |
| 20 bool* upscaleTo32) { | 54 bool* upscaleTo32) { |
| 21 if (upscaleTo32) { | 55 if (upscaleTo32) { |
| 22 *upscaleTo32 = false; | 56 *upscaleTo32 = false; |
| 23 } | 57 } |
| 24 | 58 |
| 59 const bool opaque = kOpaque_SkAlphaType == bm.alphaType(); | |
|
scroggo
2014/04/22 14:58:17
It seems like this could go in the 4444 case (the
reed1
2014/04/22 17:51:39
Done.
| |
| 60 const bool premul = kUnpremul_SkAlphaType != bm.alphaType(); | |
|
scroggo
2014/04/22 14:58:17
This variable is unused.
reed1
2014/04/22 17:51:39
Done.
| |
| 61 | |
| 25 switch (bm.colorType()) { | 62 switch (bm.colorType()) { |
| 26 case kRGB_565_SkColorType: | 63 case kRGB_565_SkColorType: |
| 27 #if 0 | 64 #if 0 |
| 28 // doesn't see quite right. Are they thinking 1555? | 65 // doesn't see quite right. Are they thinking 1555? |
| 29 *bitsPerComponent = 5; | 66 *bitsPerComponent = 5; |
| 30 *info = kCGBitmapByteOrder16Little | kCGImageAlphaNone; | 67 *info = kCGBitmapByteOrder16Little | kCGImageAlphaNone; |
| 31 break; | 68 #else |
| 32 #endif | |
| 33 if (upscaleTo32) { | 69 if (upscaleTo32) { |
| 34 *upscaleTo32 = true; | 70 *upscaleTo32 = true; |
| 35 } | 71 } |
| 36 // fall through | 72 // now treat like RGBA |
| 37 case kN32_SkColorType: | 73 *info = ComputeCGAlphaInfo_RGBA(kOpaque_SkAlphaType); |
| 74 #endif | |
| 75 break; | |
| 76 case kRGBA_8888_SkColorType: | |
| 38 *bitsPerComponent = 8; | 77 *bitsPerComponent = 8; |
| 39 #if SK_PMCOLOR_BYTE_ORDER(R,G,B,A) | 78 *info = ComputeCGAlphaInfo_RGBA(bm.alphaType()); |
| 40 *info = kCGBitmapByteOrder32Big; | 79 break; |
| 41 if (bm.isOpaque()) { | 80 case kBGRA_8888_SkColorType: |
| 42 *info |= kCGImageAlphaNoneSkipLast; | 81 *bitsPerComponent = 8; |
| 43 } else { | 82 *info = ComputeCGAlphaInfo_BGRA(bm.alphaType()); |
| 44 *info |= kCGImageAlphaPremultipliedLast; | |
| 45 } | |
| 46 #elif SK_PMCOLOR_BYTE_ORDER(B,G,R,A) | |
| 47 // Matches the CGBitmapInfo that Apple recommends for best | |
| 48 // performance, used by google chrome. | |
| 49 *info = kCGBitmapByteOrder32Little; | |
| 50 if (bm.isOpaque()) { | |
| 51 *info |= kCGImageAlphaNoneSkipFirst; | |
| 52 } else { | |
| 53 *info |= kCGImageAlphaPremultipliedFirst; | |
| 54 } | |
| 55 #else | |
| 56 // ...add more formats as required... | |
| 57 #warning Cannot convert SkBitmap to CGImageRef with these shiftmasks. \ | |
| 58 This will probably not work. | |
| 59 // Legacy behavior. Perhaps turn this into an error at some | |
| 60 // point. | |
| 61 *info = kCGBitmapByteOrder32Big; | |
| 62 if (bm.isOpaque()) { | |
| 63 *info |= kCGImageAlphaNoneSkipLast; | |
| 64 } else { | |
| 65 *info |= kCGImageAlphaPremultipliedLast; | |
| 66 } | |
| 67 #endif | |
| 68 break; | 83 break; |
| 69 case kARGB_4444_SkColorType: | 84 case kARGB_4444_SkColorType: |
| 70 *bitsPerComponent = 4; | 85 *bitsPerComponent = 4; |
| 71 *info = kCGBitmapByteOrder16Little; | 86 *info = kCGBitmapByteOrder16Little; |
| 72 if (bm.isOpaque()) { | 87 if (opaque) { |
| 73 *info |= kCGImageAlphaNoneSkipLast; | 88 *info |= kCGImageAlphaNoneSkipLast; |
| 74 } else { | 89 } else { |
| 75 *info |= kCGImageAlphaPremultipliedLast; | 90 *info |= kCGImageAlphaPremultipliedLast; |
| 76 } | 91 } |
| 77 break; | 92 break; |
| 78 default: | 93 default: |
| 79 return false; | 94 return false; |
| 80 } | 95 } |
| 81 return true; | 96 return true; |
| 82 } | 97 } |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 224 CGColorSpaceRelease(cs); | 239 CGColorSpaceRelease(cs); |
| 225 | 240 |
| 226 if (ctx) { | 241 if (ctx) { |
| 227 CGContextDrawPDFPage(ctx, page); | 242 CGContextDrawPDFPage(ctx, page); |
| 228 CGContextRelease(ctx); | 243 CGContextRelease(ctx); |
| 229 } | 244 } |
| 230 | 245 |
| 231 output->swap(bitmap); | 246 output->swap(bitmap); |
| 232 return true; | 247 return true; |
| 233 } | 248 } |
| 249 | |
| 250 //////////////////////////////////////////////////////////////////////////////// /////////////////// | |
| 251 | |
| 252 SK_API bool SkCopyPixelsFromCGImage(const SkImageInfo& info, size_t rowBytes, vo id* pixels, | |
| 253 CGImageRef image) { | |
| 254 CGBitmapInfo cg_bitmap_info = 0; | |
| 255 size_t bitsPerComponent = 0; | |
| 256 switch (info.colorType()) { | |
| 257 case kRGBA_8888_SkColorType: | |
| 258 bitsPerComponent = 8; | |
| 259 cg_bitmap_info = ComputeCGAlphaInfo_RGBA(info.alphaType()); | |
| 260 break; | |
| 261 case kBGRA_8888_SkColorType: | |
| 262 bitsPerComponent = 8; | |
| 263 cg_bitmap_info = ComputeCGAlphaInfo_BGRA(info.alphaType()); | |
| 264 break; | |
| 265 default: | |
| 266 return false; // no other colortypes are supported (for now) | |
| 267 } | |
| 268 | |
| 269 CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB(); | |
| 270 CGContextRef cg = CGBitmapContextCreate(pixels, info.width(), info.height(), bitsPerComponent, | |
| 271 rowBytes, cs, cg_bitmap_info); | |
| 272 CFRelease(cs); | |
| 273 if (NULL == cg) { | |
| 274 return false; | |
| 275 } | |
| 276 | |
| 277 // use this blend mode, to avoid having to erase the pixels first, and to av oid CG performing | |
| 278 // any blending (which could introduce errors and be slower). | |
| 279 CGContextSetBlendMode(cg, kCGBlendModeCopy); | |
| 280 | |
| 281 CGContextDrawImage(cg, CGRectMake(0, 0, info.width(), info.height()), image) ; | |
| 282 CGContextRelease(cg); | |
| 283 return true; | |
| 284 } | |
| 285 | |
| 286 bool SkCreateBitmapFromCGImage(SkBitmap* dst, CGImageRef image, SkISize* scaleTo Fit) { | |
| 287 const int width = scaleToFit ? scaleToFit->width() : SkToInt(CGImageGetWidth (image)); | |
| 288 const int height = scaleToFit ? scaleToFit->height() : SkToInt(CGImageGetHei ght(image)); | |
| 289 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height); | |
| 290 | |
| 291 SkBitmap tmp; | |
| 292 if (!tmp.allocPixels(info)) { | |
| 293 return false; | |
| 294 } | |
| 295 | |
| 296 if (!SkCopyPixelsFromCGImage(tmp.info(), tmp.rowBytes(), tmp.getPixels(), im age)) { | |
| 297 return false; | |
| 298 } | |
| 299 | |
| 300 CGImageAlphaInfo cgInfo = CGImageGetAlphaInfo(image); | |
| 301 switch (cgInfo) { | |
| 302 case kCGImageAlphaNone: | |
| 303 case kCGImageAlphaNoneSkipLast: | |
| 304 case kCGImageAlphaNoneSkipFirst: | |
| 305 SkASSERT(SkBitmap::ComputeIsOpaque(tmp)); | |
| 306 tmp.setAlphaType(kOpaque_SkAlphaType); | |
| 307 break; | |
| 308 default: | |
| 309 // we don't know if we're opaque or not, so compute it. | |
| 310 if (SkBitmap::ComputeIsOpaque(tmp)) { | |
| 311 tmp.setAlphaType(kOpaque_SkAlphaType); | |
| 312 } | |
| 313 } | |
| 314 | |
| 315 *dst = tmp; | |
| 316 return true; | |
| 317 } | |
| 318 | |
| OLD | NEW |