| OLD | NEW |
| 1 // Copyright (c) 2008 The Chromium Authors. All rights reserved. Use of this | 1 // Copyright (c) 2008 The Chromium Authors. All rights reserved. Use of this |
| 2 // source code is governed by a BSD-style license that can be found in the | 2 // source code is governed by a BSD-style license that can be found in the |
| 3 // LICENSE file. | 3 // LICENSE file. |
| 4 | 4 |
| 5 #include "webkit/glue/webcursor.h" | 5 #include "webkit/glue/webcursor.h" |
| 6 | 6 |
| 7 #import <AppKit/AppKit.h> | 7 #import <AppKit/AppKit.h> |
| 8 #include <Carbon/Carbon.h> | 8 #include <Carbon/Carbon.h> |
| 9 | 9 |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/nsimage_cache_mac.h" | 11 #include "base/nsimage_cache_mac.h" |
| 12 #include "base/scoped_cftyperef.h" | 12 #include "base/mac/scoped_cftyperef.h" |
| 13 #include "third_party/WebKit/WebKit/chromium/public/WebCursorInfo.h" | 13 #include "third_party/WebKit/WebKit/chromium/public/WebCursorInfo.h" |
| 14 #include "third_party/WebKit/WebKit/chromium/public/WebImage.h" | 14 #include "third_party/WebKit/WebKit/chromium/public/WebImage.h" |
| 15 #include "third_party/WebKit/WebKit/chromium/public/WebSize.h" | 15 #include "third_party/WebKit/WebKit/chromium/public/WebSize.h" |
| 16 | 16 |
| 17 using WebKit::WebCursorInfo; | 17 using WebKit::WebCursorInfo; |
| 18 using WebKit::WebImage; | 18 using WebKit::WebImage; |
| 19 using WebKit::WebSize; | 19 using WebKit::WebSize; |
| 20 | 20 |
| 21 namespace { | 21 namespace { |
| 22 | 22 |
| 23 // TODO: This image fetch can (and probably should) be serviced by the resource | 23 // TODO: This image fetch can (and probably should) be serviced by the resource |
| 24 // resource bundle instead of going through nsimage_cache. | 24 // resource bundle instead of going through nsimage_cache. |
| 25 NSCursor* LoadCursor(const char* name, int x, int y) { | 25 NSCursor* LoadCursor(const char* name, int x, int y) { |
| 26 NSString* file_name = [NSString stringWithUTF8String:name]; | 26 NSString* file_name = [NSString stringWithUTF8String:name]; |
| 27 DCHECK(file_name); | 27 DCHECK(file_name); |
| 28 NSImage* cursor_image = nsimage_cache::ImageNamed(file_name); | 28 NSImage* cursor_image = nsimage_cache::ImageNamed(file_name); |
| 29 DCHECK(cursor_image); | 29 DCHECK(cursor_image); |
| 30 return [[[NSCursor alloc] initWithImage:cursor_image | 30 return [[[NSCursor alloc] initWithImage:cursor_image |
| 31 hotSpot:NSMakePoint(x, y)] autorelease]; | 31 hotSpot:NSMakePoint(x, y)] autorelease]; |
| 32 } | 32 } |
| 33 | 33 |
| 34 CGImageRef CreateCGImageFromCustomData(const std::vector<char>& custom_data, | 34 CGImageRef CreateCGImageFromCustomData(const std::vector<char>& custom_data, |
| 35 const gfx::Size& custom_size) { | 35 const gfx::Size& custom_size) { |
| 36 scoped_cftyperef<CGColorSpaceRef> cg_color(CGColorSpaceCreateDeviceRGB()); | 36 base::mac::ScopedCFTypeRef<CGColorSpaceRef> cg_color( |
| 37 CGColorSpaceCreateDeviceRGB()); |
| 37 // This is safe since we're not going to draw into the context we're creating. | 38 // This is safe since we're not going to draw into the context we're creating. |
| 38 void* data = const_cast<char*>(&custom_data[0]); | 39 void* data = const_cast<char*>(&custom_data[0]); |
| 39 // The settings here match SetCustomData() below; keep in sync. | 40 // The settings here match SetCustomData() below; keep in sync. |
| 40 scoped_cftyperef<CGContextRef> context( | 41 base::mac::ScopedCFTypeRef<CGContextRef> context( |
| 41 CGBitmapContextCreate(data, | 42 CGBitmapContextCreate(data, |
| 42 custom_size.width(), | 43 custom_size.width(), |
| 43 custom_size.height(), | 44 custom_size.height(), |
| 44 8, | 45 8, |
| 45 custom_size.width()*4, | 46 custom_size.width()*4, |
| 46 cg_color.get(), | 47 cg_color.get(), |
| 47 kCGImageAlphaPremultipliedLast | | 48 kCGImageAlphaPremultipliedLast | |
| 48 kCGBitmapByteOrder32Big)); | 49 kCGBitmapByteOrder32Big)); |
| 49 return CGBitmapContextCreateImage(context.get()); | 50 return CGBitmapContextCreateImage(context.get()); |
| 50 } | 51 } |
| 51 | 52 |
| 52 NSCursor* CreateCustomCursor(const std::vector<char>& custom_data, | 53 NSCursor* CreateCustomCursor(const std::vector<char>& custom_data, |
| 53 const gfx::Size& custom_size, | 54 const gfx::Size& custom_size, |
| 54 const gfx::Point& hotspot) { | 55 const gfx::Point& hotspot) { |
| 55 // CG throws a cocoa exception if we try to create an empty image, which | 56 // CG throws a cocoa exception if we try to create an empty image, which |
| 56 // results in an infinite loop. This CHECK ensures that we crash instead. | 57 // results in an infinite loop. This CHECK ensures that we crash instead. |
| 57 CHECK(!custom_data.empty()); | 58 CHECK(!custom_data.empty()); |
| 58 | 59 |
| 59 scoped_cftyperef<CGImageRef> cg_image( | 60 base::mac::ScopedCFTypeRef<CGImageRef> cg_image( |
| 60 CreateCGImageFromCustomData(custom_data, custom_size)); | 61 CreateCGImageFromCustomData(custom_data, custom_size)); |
| 61 | 62 |
| 62 NSBitmapImageRep* ns_bitmap = | 63 NSBitmapImageRep* ns_bitmap = |
| 63 [[NSBitmapImageRep alloc] initWithCGImage:cg_image.get()]; | 64 [[NSBitmapImageRep alloc] initWithCGImage:cg_image.get()]; |
| 64 NSImage* cursor_image = [[NSImage alloc] init]; | 65 NSImage* cursor_image = [[NSImage alloc] init]; |
| 65 DCHECK(cursor_image); | 66 DCHECK(cursor_image); |
| 66 [cursor_image addRepresentation:ns_bitmap]; | 67 [cursor_image addRepresentation:ns_bitmap]; |
| 67 [ns_bitmap release]; | 68 [ns_bitmap release]; |
| 68 | 69 |
| 69 NSCursor* cursor = [[NSCursor alloc] initWithImage:cursor_image | 70 NSCursor* cursor = [[NSCursor alloc] initWithImage:cursor_image |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 251 } | 252 } |
| 252 if (mask & 0x8000) | 253 if (mask & 0x8000) |
| 253 raw_data.push_back(0xFF); | 254 raw_data.push_back(0xFF); |
| 254 else | 255 else |
| 255 raw_data.push_back(0x00); | 256 raw_data.push_back(0x00); |
| 256 data <<= 1; | 257 data <<= 1; |
| 257 mask <<= 1; | 258 mask <<= 1; |
| 258 } | 259 } |
| 259 } | 260 } |
| 260 | 261 |
| 261 scoped_cftyperef<CGImageRef> cg_image( | 262 base::mac::ScopedCFTypeRef<CGImageRef> cg_image( |
| 262 CreateCGImageFromCustomData(raw_data, custom_size)); | 263 CreateCGImageFromCustomData(raw_data, custom_size)); |
| 263 | 264 |
| 264 WebKit::WebCursorInfo cursor_info; | 265 WebKit::WebCursorInfo cursor_info; |
| 265 cursor_info.type = WebCursorInfo::TypeCustom; | 266 cursor_info.type = WebCursorInfo::TypeCustom; |
| 266 cursor_info.hotSpot = WebKit::WebPoint(cursor->hotSpot.h, cursor->hotSpot.v); | 267 cursor_info.hotSpot = WebKit::WebPoint(cursor->hotSpot.h, cursor->hotSpot.v); |
| 267 cursor_info.customImage = cg_image.get(); | 268 cursor_info.customImage = cg_image.get(); |
| 268 | 269 |
| 269 InitFromCursorInfo(cursor_info); | 270 InitFromCursorInfo(cursor_info); |
| 270 } | 271 } |
| 271 | 272 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 315 } | 316 } |
| 316 } | 317 } |
| 317 | 318 |
| 318 InitFromCursorInfo(cursor_info); | 319 InitFromCursorInfo(cursor_info); |
| 319 } | 320 } |
| 320 | 321 |
| 321 void WebCursor::SetCustomData(const WebImage& image) { | 322 void WebCursor::SetCustomData(const WebImage& image) { |
| 322 if (image.isNull()) | 323 if (image.isNull()) |
| 323 return; | 324 return; |
| 324 | 325 |
| 325 scoped_cftyperef<CGColorSpaceRef> cg_color( | 326 base::mac::ScopedCFTypeRef<CGColorSpaceRef> cg_color( |
| 326 CGColorSpaceCreateDeviceRGB()); | 327 CGColorSpaceCreateDeviceRGB()); |
| 327 | 328 |
| 328 const WebSize& image_dimensions = image.size(); | 329 const WebSize& image_dimensions = image.size(); |
| 329 int image_width = image_dimensions.width; | 330 int image_width = image_dimensions.width; |
| 330 int image_height = image_dimensions.height; | 331 int image_height = image_dimensions.height; |
| 331 | 332 |
| 332 size_t size = image_height * image_width * 4; | 333 size_t size = image_height * image_width * 4; |
| 333 custom_data_.resize(size); | 334 custom_data_.resize(size); |
| 334 custom_size_.set_width(image_width); | 335 custom_size_.set_width(image_width); |
| 335 custom_size_.set_height(image_height); | 336 custom_size_.set_height(image_height); |
| 336 | 337 |
| 337 // These settings match up with the code in CreateCustomCursor() above; keep | 338 // These settings match up with the code in CreateCustomCursor() above; keep |
| 338 // them in sync. | 339 // them in sync. |
| 339 // TODO(avi): test to ensure that the flags here are correct for RGBA | 340 // TODO(avi): test to ensure that the flags here are correct for RGBA |
| 340 scoped_cftyperef<CGContextRef> context( | 341 base::mac::ScopedCFTypeRef<CGContextRef> context( |
| 341 CGBitmapContextCreate(&custom_data_[0], | 342 CGBitmapContextCreate(&custom_data_[0], |
| 342 image_width, | 343 image_width, |
| 343 image_height, | 344 image_height, |
| 344 8, | 345 8, |
| 345 image_width * 4, | 346 image_width * 4, |
| 346 cg_color.get(), | 347 cg_color.get(), |
| 347 kCGImageAlphaPremultipliedLast | | 348 kCGImageAlphaPremultipliedLast | |
| 348 kCGBitmapByteOrder32Big)); | 349 kCGBitmapByteOrder32Big)); |
| 349 CGRect rect = CGRectMake(0, 0, image_width, image_height); | 350 CGRect rect = CGRectMake(0, 0, image_width, image_height); |
| 350 CGContextDrawImage(context.get(), rect, image.getCGImageRef()); | 351 CGContextDrawImage(context.get(), rect, image.getCGImageRef()); |
| 351 } | 352 } |
| 352 | 353 |
| 353 void WebCursor::ImageFromCustomData(WebImage* image) const { | 354 void WebCursor::ImageFromCustomData(WebImage* image) const { |
| 354 if (custom_data_.empty()) | 355 if (custom_data_.empty()) |
| 355 return; | 356 return; |
| 356 | 357 |
| 357 scoped_cftyperef<CGImageRef> cg_image( | 358 base::mac::ScopedCFTypeRef<CGImageRef> cg_image( |
| 358 CreateCGImageFromCustomData(custom_data_, custom_size_)); | 359 CreateCGImageFromCustomData(custom_data_, custom_size_)); |
| 359 *image = cg_image.get(); | 360 *image = cg_image.get(); |
| 360 } | 361 } |
| 361 | 362 |
| 362 void WebCursor::InitPlatformData() { | 363 void WebCursor::InitPlatformData() { |
| 363 return; | 364 return; |
| 364 } | 365 } |
| 365 | 366 |
| 366 bool WebCursor::SerializePlatformData(Pickle* pickle) const { | 367 bool WebCursor::SerializePlatformData(Pickle* pickle) const { |
| 367 return true; | 368 return true; |
| 368 } | 369 } |
| 369 | 370 |
| 370 bool WebCursor::DeserializePlatformData(const Pickle* pickle, void** iter) { | 371 bool WebCursor::DeserializePlatformData(const Pickle* pickle, void** iter) { |
| 371 return true; | 372 return true; |
| 372 } | 373 } |
| 373 | 374 |
| 374 bool WebCursor::IsPlatformDataEqual(const WebCursor& other) const { | 375 bool WebCursor::IsPlatformDataEqual(const WebCursor& other) const { |
| 375 return true; | 376 return true; |
| 376 } | 377 } |
| 377 | 378 |
| 378 void WebCursor::CleanupPlatformData() { | 379 void WebCursor::CleanupPlatformData() { |
| 379 return; | 380 return; |
| 380 } | 381 } |
| 381 | 382 |
| 382 void WebCursor::CopyPlatformData(const WebCursor& other) { | 383 void WebCursor::CopyPlatformData(const WebCursor& other) { |
| 383 return; | 384 return; |
| 384 } | 385 } |
| OLD | NEW |