| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <base/logging.h> | 5 #include <base/logging.h> |
| 6 #include "chrome/browser/cocoa/cocoa_utils.h" | 6 #include "chrome/browser/cocoa/cocoa_utils.h" |
| 7 #import <QuartzCore/CIImage.h> | 7 #import <QuartzCore/CIImage.h> |
| 8 #include "third_party/skia/include/utils/mac/SkCGUtils.h" | 8 #include "third_party/skia/include/utils/mac/SkCGUtils.h" |
| 9 #include "third_party/skia/include/core/SkColorPriv.h" | 9 #include "third_party/skia/include/core/SkColorPriv.h" |
| 10 | 10 |
| 11 namespace { | 11 namespace { |
| 12 | 12 |
| 13 // Callback passed to CGDataProviderCreateWithData() | 13 // Callback passed to CGDataProviderCreateWithData() |
| 14 void ReleaseData(void* info, const void* pixelData, size_t size) { | 14 void ReleaseData(void* info, const void* pixelData, size_t size) { |
| 15 // info is a non-const pixelData | 15 // info is a non-const pixelData |
| 16 if (info) | 16 if (info) |
| 17 free(info); | 17 free(info); |
| 18 } | 18 } |
| 19 | 19 |
| 20 } | 20 } |
| 21 | 21 |
| 22 namespace CocoaUtils { | 22 namespace CocoaUtils { |
| 23 | 23 |
| 24 NSImage* SkBitmapToNSImage(const SkBitmap& icon) { | 24 NSImage* SkBitmapToNSImage(const SkBitmap& skiaBitmap) { |
| 25 // First convert SkBitmap to CGImageRef. | 25 // First convert SkBitmap to CGImageRef. |
| 26 CGImageRef cgimage; | 26 CGImageRef cgimage = SkCreateCGImageRef(skiaBitmap); |
| 27 if (icon.config() != SkBitmap::kARGB_8888_Config) { | |
| 28 cgimage = SkCreateCGImageRef(icon); | |
| 29 } else { | |
| 30 // The above code returns a valid NSImage even in the | |
| 31 // kARGB_8888_Config case. As an example, the unit test which | |
| 32 // draws a blue SkBitmap can lockPixels, NSReadPixel, and pull out | |
| 33 // a single pixel from the NSImage and see it blue. However, the | |
| 34 // NSImage returned will be in ABGR format. Although Cocoa is | |
| 35 // otherwise happy with that format (as seen in simple tests | |
| 36 // outside Chromium), Chromium is NOT happy. In Chromium, B and R | |
| 37 // are swapped. | |
| 38 // | |
| 39 // As a hint, CIImage supports a few formats, such as ARGB. | |
| 40 // Interestingly, it does NOT support ABGR. I speculate there is | |
| 41 // some way we set up our drawing context which has the format | |
| 42 // specified wrong (in skia/ext/bitmap_platform_device_mac.cc), | |
| 43 // but I have not been able to solve this yet. | |
| 44 // | |
| 45 // TODO(jrg): track down the disconnect. | |
| 46 // TODO(jrg): Remove byte conversion. | |
| 47 // TODO(jrg): Fix unit tests to NOT swap bytes. | |
| 48 // http://crbug.com/14020 | |
| 49 CGBitmapInfo info = (kCGImageAlphaPremultipliedFirst | | |
| 50 kCGBitmapByteOrder32Host); | |
| 51 int width = icon.width(); | |
| 52 int height = icon.height(); | |
| 53 int rowbytes = icon.rowBytes(); | |
| 54 int rowwords = rowbytes/4; | |
| 55 unsigned length = rowbytes * height; | |
| 56 DCHECK(length > 0); | |
| 57 uint32_t* rawptr = static_cast<uint32_t*>(malloc(length)); | |
| 58 DCHECK(rawptr); | |
| 59 if (!rawptr || !length) | |
| 60 return nil; | |
| 61 | |
| 62 // Convert ABGR to ARGB | |
| 63 icon.lockPixels(); | |
| 64 uint32_t* rawbitmap = static_cast<uint32_t*>(icon.getPixels()); | |
| 65 uint32_t rawbit; | |
| 66 int offset; | |
| 67 for (int y = 0; y < height; y++) { | |
| 68 for (int x = 0; x < width; x++) { | |
| 69 offset = x + y*rowwords; | |
| 70 rawbit = rawbitmap[offset]; | |
| 71 rawptr[offset] = SkPackARGB32(SkGetPackedA32(rawbit), | |
| 72 SkGetPackedR32(rawbit), | |
| 73 SkGetPackedG32(rawbit), | |
| 74 SkGetPackedB32(rawbit)); | |
| 75 } | |
| 76 } | |
| 77 icon.unlockPixels(); | |
| 78 | |
| 79 CGDataProviderRef dataRef = | |
| 80 CGDataProviderCreateWithData(rawptr, rawptr, length, ReleaseData); | |
| 81 CGColorSpaceRef space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); | |
| 82 cgimage = CGImageCreate(width, height, 8, | |
| 83 icon.bytesPerPixel() * 8, | |
| 84 rowbytes, space, info, dataRef, | |
| 85 NULL, false, kCGRenderingIntentDefault); | |
| 86 CGColorSpaceRelease(space); | |
| 87 CGDataProviderRelease(dataRef); | |
| 88 } | |
| 89 | 27 |
| 90 // Now convert to NSImage. | 28 // Now convert to NSImage. |
| 91 NSBitmapImageRep* bitmap = [[[NSBitmapImageRep alloc] | 29 NSBitmapImageRep* bitmap = [[[NSBitmapImageRep alloc] |
| 92 initWithCGImage:cgimage] autorelease]; | 30 initWithCGImage:cgimage] autorelease]; |
| 93 CFRelease(cgimage); | 31 CFRelease(cgimage); |
| 94 NSImage* image = [[[NSImage alloc] init] autorelease]; | 32 NSImage* image = [[[NSImage alloc] init] autorelease]; |
| 95 [image addRepresentation:bitmap]; | 33 [image addRepresentation:bitmap]; |
| 96 return image; | 34 return image; |
| 97 } | 35 } |
| 98 | 36 |
| 99 } // namespace CocoaUtils | 37 } // namespace CocoaUtils |
| 100 | 38 |
| OLD | NEW |