| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "skia/ext/skia_utils_mac.h" | 5 #include "skia/ext/skia_utils_mac.h" |
| 6 | 6 |
| 7 #import <AppKit/AppKit.h> | 7 #import <AppKit/AppKit.h> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/mac/scoped_cftyperef.h" | 10 #include "base/mac/scoped_cftyperef.h" |
| 11 #include "base/memory/scoped_nsobject.h" |
| 11 #include "base/memory/scoped_ptr.h" | 12 #include "base/memory/scoped_ptr.h" |
| 12 #include "skia/ext/bitmap_platform_device_mac.h" | 13 #include "skia/ext/bitmap_platform_device_mac.h" |
| 13 #include "third_party/skia/include/utils/mac/SkCGUtils.h" | 14 #include "third_party/skia/include/utils/mac/SkCGUtils.h" |
| 14 | 15 |
| 15 namespace gfx { | 16 namespace gfx { |
| 16 | 17 |
| 17 CGAffineTransform SkMatrixToCGAffineTransform(const SkMatrix& matrix) { | 18 CGAffineTransform SkMatrixToCGAffineTransform(const SkMatrix& matrix) { |
| 18 // CGAffineTransforms don't support perspective transforms, so make sure | 19 // CGAffineTransforms don't support perspective transforms, so make sure |
| 19 // we don't get those. | 20 // we don't get those. |
| 20 DCHECK(matrix[SkMatrix::kMPersp0] == 0.0f); | 21 DCHECK(matrix[SkMatrix::kMPersp0] == 0.0f); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 109 CGContextDrawImage(context, rect, image); | 110 CGContextDrawImage(context, rect, image); |
| 110 | 111 |
| 111 // Because |device| will be cleaned up and will take its pixels with it, we | 112 // Because |device| will be cleaned up and will take its pixels with it, we |
| 112 // copy it to the stack and return it. | 113 // copy it to the stack and return it. |
| 113 SkBitmap bitmap = device->accessBitmap(false); | 114 SkBitmap bitmap = device->accessBitmap(false); |
| 114 | 115 |
| 115 return bitmap; | 116 return bitmap; |
| 116 } | 117 } |
| 117 | 118 |
| 118 SkBitmap NSImageToSkBitmap(NSImage* image, NSSize size, bool is_opaque) { | 119 SkBitmap NSImageToSkBitmap(NSImage* image, NSSize size, bool is_opaque) { |
| 120 return NSImageRepToSkBitmap([image bestRepresentationForDevice:nil], |
| 121 size, is_opaque); |
| 122 } |
| 123 |
| 124 SkBitmap NSImageRepToSkBitmap(NSImageRep* image, NSSize size, bool is_opaque) { |
| 119 SkBitmap bitmap; | 125 SkBitmap bitmap; |
| 120 bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width, size.height); | 126 bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width, size.height); |
| 121 if (bitmap.allocPixels() != true) | 127 if (!bitmap.allocPixels()) |
| 122 return bitmap; // Return |bitmap| which should respond true to isNull(). | 128 return bitmap; // Return |bitmap| which should respond true to isNull(). |
| 123 | 129 |
| 124 bitmap.setIsOpaque(is_opaque); | 130 bitmap.setIsOpaque(is_opaque); |
| 125 | 131 |
| 126 base::mac::ScopedCFTypeRef<CGColorSpaceRef> color_space( | 132 base::mac::ScopedCFTypeRef<CGColorSpaceRef> color_space( |
| 127 CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB)); | 133 CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB)); |
| 128 void* data = bitmap.getPixels(); | 134 void* data = bitmap.getPixels(); |
| 129 | 135 |
| 130 // Allocate a bitmap context with 4 components per pixel (BGRA). Apple | 136 // Allocate a bitmap context with 4 components per pixel (BGRA). Apple |
| 131 // recommends these flags for improved CG performance. | 137 // recommends these flags for improved CG performance. |
| 132 #define HAS_ARGB_SHIFTS(a, r, g, b) \ | 138 #define HAS_ARGB_SHIFTS(a, r, g, b) \ |
| 133 (SK_A32_SHIFT == (a) && SK_R32_SHIFT == (r) \ | 139 (SK_A32_SHIFT == (a) && SK_R32_SHIFT == (r) \ |
| 134 && SK_G32_SHIFT == (g) && SK_B32_SHIFT == (b)) | 140 && SK_G32_SHIFT == (g) && SK_B32_SHIFT == (b)) |
| 135 #if defined(SK_CPU_LENDIAN) && HAS_ARGB_SHIFTS(24, 16, 8, 0) | 141 #if defined(SK_CPU_LENDIAN) && HAS_ARGB_SHIFTS(24, 16, 8, 0) |
| 136 base::mac::ScopedCFTypeRef<CGContextRef> context( | 142 base::mac::ScopedCFTypeRef<CGContextRef> context( |
| 137 CGBitmapContextCreate(data, size.width, size.height, 8, size.width*4, | 143 CGBitmapContextCreate(data, size.width, size.height, 8, size.width*4, |
| 138 color_space, | 144 color_space, |
| 139 kCGImageAlphaPremultipliedFirst | | 145 kCGImageAlphaPremultipliedFirst | |
| 140 kCGBitmapByteOrder32Host)); | 146 kCGBitmapByteOrder32Host)); |
| 141 #else | 147 #else |
| 142 #error We require that Skia's and CoreGraphics's recommended \ | 148 #error We require that Skia's and CoreGraphics's recommended \ |
| 143 image memory layout match. | 149 image memory layout match. |
| 144 #endif | 150 #endif |
| 145 #undef HAS_ARGB_SHIFTS | 151 #undef HAS_ARGB_SHIFTS |
| 146 | 152 |
| 147 // Something went really wrong. Best guess is that the bitmap data is invalid. | 153 // Something went really wrong. Best guess is that the bitmap data is invalid. |
| 148 DCHECK(context != NULL); | 154 DCHECK(context); |
| 149 | 155 |
| 150 // Save the current graphics context so that we can restore it later. | 156 // Save the current graphics context so that we can restore it later. |
| 151 [NSGraphicsContext saveGraphicsState]; | 157 [NSGraphicsContext saveGraphicsState]; |
| 152 | 158 |
| 153 // Dummy context that we will draw into. | 159 // Dummy context that we will draw into. |
| 154 NSGraphicsContext* context_cocoa = | 160 NSGraphicsContext* context_cocoa = |
| 155 [NSGraphicsContext graphicsContextWithGraphicsPort:context flipped:NO]; | 161 [NSGraphicsContext graphicsContextWithGraphicsPort:context flipped:NO]; |
| 156 [NSGraphicsContext setCurrentContext:context_cocoa]; | 162 [NSGraphicsContext setCurrentContext:context_cocoa]; |
| 157 | 163 |
| 158 // This will stretch any images to |size| if it does not fit or is non-square. | 164 // This will stretch any images to |size| if it does not fit or is non-square. |
| 159 [image drawInRect:NSMakeRect(0, 0, size.width, size.height) | 165 [image drawInRect:NSMakeRect(0, 0, size.width, size.height)]; |
| 160 fromRect:NSZeroRect | |
| 161 operation:NSCompositeCopy | |
| 162 fraction:1.0]; | |
| 163 | 166 |
| 164 // Done drawing, restore context. | 167 // Done drawing, restore context. |
| 165 [NSGraphicsContext restoreGraphicsState]; | 168 [NSGraphicsContext restoreGraphicsState]; |
| 166 | 169 |
| 167 return bitmap; | 170 return bitmap; |
| 168 } | 171 } |
| 169 | 172 |
| 170 NSImage* SkBitmapToNSImageWithColorSpace(const SkBitmap& skiaBitmap, | 173 NSImage* SkBitmapToNSImageWithColorSpace(const SkBitmap& skiaBitmap, |
| 171 CGColorSpaceRef colorSpace) { | 174 CGColorSpaceRef colorSpace) { |
| 172 if (skiaBitmap.isNull()) | 175 if (skiaBitmap.isNull()) |
| 173 return nil; | 176 return nil; |
| 174 | 177 |
| 175 // First convert SkBitmap to CGImageRef. | 178 // First convert SkBitmap to CGImageRef. |
| 176 CGImageRef cgimage = | 179 base::mac::ScopedCFTypeRef<CGImageRef> cgimage( |
| 177 SkCreateCGImageRefWithColorspace(skiaBitmap, colorSpace); | 180 SkCreateCGImageRefWithColorspace(skiaBitmap, colorSpace)); |
| 178 | 181 |
| 179 // Now convert to NSImage. | 182 // Now convert to NSImage. |
| 180 NSBitmapImageRep* bitmap = [[[NSBitmapImageRep alloc] | 183 scoped_nsobject<NSBitmapImageRep> bitmap( |
| 181 initWithCGImage:cgimage] autorelease]; | 184 [[NSBitmapImageRep alloc] initWithCGImage:cgimage]); |
| 182 CFRelease(cgimage); | |
| 183 NSImage* image = [[[NSImage alloc] init] autorelease]; | 185 NSImage* image = [[[NSImage alloc] init] autorelease]; |
| 184 [image addRepresentation:bitmap]; | 186 [image addRepresentation:bitmap]; |
| 185 [image setSize:NSMakeSize(skiaBitmap.width(), skiaBitmap.height())]; | 187 [image setSize:NSMakeSize(skiaBitmap.width(), skiaBitmap.height())]; |
| 186 return image; | 188 return image; |
| 187 } | 189 } |
| 188 | 190 |
| 189 NSImage* SkBitmapToNSImage(const SkBitmap& skiaBitmap) { | 191 NSImage* SkBitmapToNSImage(const SkBitmap& skiaBitmap) { |
| 190 base::mac::ScopedCFTypeRef<CGColorSpaceRef> colorSpace( | 192 base::mac::ScopedCFTypeRef<CGColorSpaceRef> colorSpace( |
| 191 CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB)); | 193 CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB)); |
| 192 return SkBitmapToNSImageWithColorSpace(skiaBitmap, colorSpace.get()); | 194 return SkBitmapToNSImageWithColorSpace(skiaBitmap, colorSpace.get()); |
| 193 } | 195 } |
| 194 | 196 |
| 197 NSImage* SkBitmapsToNSImage(const std::vector<const SkBitmap*>& bitmaps) { |
| 198 if (bitmaps.empty()) |
| 199 return nil; |
| 200 |
| 201 base::mac::ScopedCFTypeRef<CGColorSpaceRef> colorSpace( |
| 202 CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB)); |
| 203 NSImage* image = [[[NSImage alloc] init] autorelease]; |
| 204 NSSize minSize = NSZeroSize; |
| 205 |
| 206 for (std::vector<const SkBitmap*>::const_iterator it = bitmaps.begin(); |
| 207 it != bitmaps.end(); ++it) { |
| 208 const SkBitmap& skiaBitmap = **it; |
| 209 // First convert SkBitmap to CGImageRef. |
| 210 base::mac::ScopedCFTypeRef<CGImageRef> cgimage( |
| 211 SkCreateCGImageRefWithColorspace(skiaBitmap, colorSpace)); |
| 212 |
| 213 // Now convert to NSImage. |
| 214 scoped_nsobject<NSBitmapImageRep> bitmap( |
| 215 [[NSBitmapImageRep alloc] initWithCGImage:cgimage]); |
| 216 [image addRepresentation:bitmap]; |
| 217 |
| 218 if (minSize.width == 0 || minSize.width < skiaBitmap.width()) { |
| 219 minSize.width = skiaBitmap.width(); |
| 220 minSize.height = skiaBitmap.height(); |
| 221 } |
| 222 } |
| 223 |
| 224 [image setSize:minSize]; |
| 225 return image; |
| 226 } |
| 227 |
| 195 SkBitmap AppplicationIconAtSize(int size) { | 228 SkBitmap AppplicationIconAtSize(int size) { |
| 196 NSImage* image = [NSImage imageNamed:@"NSApplicationIcon"]; | 229 NSImage* image = [NSImage imageNamed:@"NSApplicationIcon"]; |
| 197 return NSImageToSkBitmap(image, NSMakeSize(size, size), /* is_opaque=*/true); | 230 return NSImageToSkBitmap(image, NSMakeSize(size, size), /* is_opaque=*/true); |
| 198 } | 231 } |
| 199 | 232 |
| 200 } // namespace gfx | 233 } // namespace gfx |
| OLD | NEW |