| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "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/mac/mac_util.h" | 11 #include "base/mac/mac_util.h" |
| 12 #include "base/mac/scoped_cftyperef.h" | 12 #include "base/mac/scoped_cftyperef.h" |
| 13 #include "base/memory/scoped_nsobject.h" | 13 #include "base/memory/scoped_nsobject.h" |
| 14 #include "skia/ext/skia_utils_mac.h" |
| 14 #include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h" | 15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h" |
| 15 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebImage.h" | 16 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebImage.h" |
| 16 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSize.h" | 17 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSize.h" |
| 17 #include "ui/gfx/mac/nsimage_cache.h" | 18 #include "ui/gfx/mac/nsimage_cache.h" |
| 18 | 19 |
| 19 #if WEBKIT_USING_SKIA | |
| 20 #include "skia/ext/skia_utils_mac.h" | |
| 21 #endif | |
| 22 | |
| 23 using WebKit::WebCursorInfo; | 20 using WebKit::WebCursorInfo; |
| 24 using WebKit::WebImage; | 21 using WebKit::WebImage; |
| 25 using WebKit::WebSize; | 22 using WebKit::WebSize; |
| 26 | 23 |
| 27 // Declare symbols that are part of the 10.6 SDK. | 24 // Declare symbols that are part of the 10.6 SDK. |
| 28 #if !defined(MAC_OS_X_VERSION_10_6) || \ | 25 #if !defined(MAC_OS_X_VERSION_10_6) || \ |
| 29 MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6 | 26 MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6 |
| 30 | 27 |
| 31 @interface NSCursor (SnowLeopardSDKDeclarations) | 28 @interface NSCursor (SnowLeopardSDKDeclarations) |
| 32 + (NSCursor*)contextualMenuCursor; | 29 + (NSCursor*)contextualMenuCursor; |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 89 size.width()*4, | 86 size.width()*4, |
| 90 cg_color.get(), | 87 cg_color.get(), |
| 91 kCGImageAlphaPremultipliedLast | | 88 kCGImageAlphaPremultipliedLast | |
| 92 kCGBitmapByteOrder32Big)); | 89 kCGBitmapByteOrder32Big)); |
| 93 return CGBitmapContextCreateImage(context.get()); | 90 return CGBitmapContextCreateImage(context.get()); |
| 94 } | 91 } |
| 95 | 92 |
| 96 NSCursor* CreateCustomCursor(const std::vector<char>& custom_data, | 93 NSCursor* CreateCustomCursor(const std::vector<char>& custom_data, |
| 97 const gfx::Size& custom_size, | 94 const gfx::Size& custom_size, |
| 98 const gfx::Point& hotspot) { | 95 const gfx::Point& hotspot) { |
| 99 #if WEBKIT_USING_SKIA | |
| 100 // If the data is missing, leave the backing transparent. | 96 // If the data is missing, leave the backing transparent. |
| 101 void* data = NULL; | 97 void* data = NULL; |
| 102 size_t data_size = 0; | 98 size_t data_size = 0; |
| 103 if (!custom_data.empty()) { | 99 if (!custom_data.empty()) { |
| 104 // This is safe since we're not going to draw into the context we're | 100 // This is safe since we're not going to draw into the context we're |
| 105 // creating. | 101 // creating. |
| 106 data = const_cast<char*>(&custom_data[0]); | 102 data = const_cast<char*>(&custom_data[0]); |
| 107 data_size = custom_data.size(); | 103 data_size = custom_data.size(); |
| 108 } | 104 } |
| 109 | 105 |
| 110 // If the size is empty, use a 1x1 transparent image. | 106 // If the size is empty, use a 1x1 transparent image. |
| 111 gfx::Size size = custom_size; | 107 gfx::Size size = custom_size; |
| 112 if (size.IsEmpty()) { | 108 if (size.IsEmpty()) { |
| 113 size.SetSize(1, 1); | 109 size.SetSize(1, 1); |
| 114 data = NULL; | 110 data = NULL; |
| 115 } | 111 } |
| 116 | 112 |
| 117 SkBitmap bitmap; | 113 SkBitmap bitmap; |
| 118 bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height()); | 114 bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height()); |
| 119 bitmap.allocPixels(); | 115 bitmap.allocPixels(); |
| 120 if (data) | 116 if (data) |
| 121 memcpy(bitmap.getAddr32(0, 0), data, data_size); | 117 memcpy(bitmap.getAddr32(0, 0), data, data_size); |
| 122 else | 118 else |
| 123 bitmap.eraseARGB(0, 0, 0, 0); | 119 bitmap.eraseARGB(0, 0, 0, 0); |
| 124 NSImage* cursor_image = gfx::SkBitmapToNSImage(bitmap); | 120 NSImage* cursor_image = gfx::SkBitmapToNSImage(bitmap); |
| 125 #else | |
| 126 base::mac::ScopedCFTypeRef<CGImageRef> cg_image( | |
| 127 CreateCGImageFromCustomData(custom_data, custom_size)); | |
| 128 | |
| 129 scoped_nsobject<NSBitmapImageRep> ns_bitmap( | |
| 130 [[NSBitmapImageRep alloc] initWithCGImage:cg_image.get()]); | |
| 131 scoped_nsobject<NSImage> cursor_image([[NSImage alloc] init]); | |
| 132 DCHECK(cursor_image); | |
| 133 [cursor_image addRepresentation:ns_bitmap]; | |
| 134 #endif // WEBKIT_USING_SKIA | |
| 135 | 121 |
| 136 NSCursor* cursor = [[NSCursor alloc] initWithImage:cursor_image | 122 NSCursor* cursor = [[NSCursor alloc] initWithImage:cursor_image |
| 137 hotSpot:NSMakePoint(hotspot.x(), | 123 hotSpot:NSMakePoint(hotspot.x(), |
| 138 hotspot.y())]; | 124 hotspot.y())]; |
| 139 | 125 |
| 140 return [cursor autorelease]; | 126 return [cursor autorelease]; |
| 141 } | 127 } |
| 142 | 128 |
| 143 } // namespace | 129 } // namespace |
| 144 | 130 |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 356 mask <<= 1; | 342 mask <<= 1; |
| 357 } | 343 } |
| 358 } | 344 } |
| 359 | 345 |
| 360 base::mac::ScopedCFTypeRef<CGImageRef> cg_image( | 346 base::mac::ScopedCFTypeRef<CGImageRef> cg_image( |
| 361 CreateCGImageFromCustomData(raw_data, custom_size)); | 347 CreateCGImageFromCustomData(raw_data, custom_size)); |
| 362 | 348 |
| 363 WebKit::WebCursorInfo cursor_info; | 349 WebKit::WebCursorInfo cursor_info; |
| 364 cursor_info.type = WebCursorInfo::TypeCustom; | 350 cursor_info.type = WebCursorInfo::TypeCustom; |
| 365 cursor_info.hotSpot = WebKit::WebPoint(cursor->hotSpot.h, cursor->hotSpot.v); | 351 cursor_info.hotSpot = WebKit::WebPoint(cursor->hotSpot.h, cursor->hotSpot.v); |
| 366 #if WEBKIT_USING_SKIA | |
| 367 // TODO(avi): build the cursor image in Skia directly rather than going via | 352 // TODO(avi): build the cursor image in Skia directly rather than going via |
| 368 // this roundabout path. | 353 // this roundabout path. |
| 369 cursor_info.customImage = gfx::CGImageToSkBitmap(cg_image.get()); | 354 cursor_info.customImage = gfx::CGImageToSkBitmap(cg_image.get()); |
| 370 #else | |
| 371 cursor_info.customImage = cg_image.get(); | |
| 372 #endif | |
| 373 | 355 |
| 374 InitFromCursorInfo(cursor_info); | 356 InitFromCursorInfo(cursor_info); |
| 375 } | 357 } |
| 376 | 358 |
| 377 void WebCursor::InitFromNSCursor(NSCursor* cursor) { | 359 void WebCursor::InitFromNSCursor(NSCursor* cursor) { |
| 378 WebKit::WebCursorInfo cursor_info; | 360 WebKit::WebCursorInfo cursor_info; |
| 379 | 361 |
| 380 if ([cursor isEqual:[NSCursor arrowCursor]]) { | 362 if ([cursor isEqual:[NSCursor arrowCursor]]) { |
| 381 cursor_info.type = WebCursorInfo::TypePointer; | 363 cursor_info.type = WebCursorInfo::TypePointer; |
| 382 } else if ([cursor isEqual:[NSCursor IBeamCursor]]) { | 364 } else if ([cursor isEqual:[NSCursor IBeamCursor]]) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 422 if ([rep isKindOfClass:[NSBitmapImageRep class]]) { | 404 if ([rep isKindOfClass:[NSBitmapImageRep class]]) { |
| 423 cg_image = [rep CGImage]; | 405 cg_image = [rep CGImage]; |
| 424 break; | 406 break; |
| 425 } | 407 } |
| 426 } | 408 } |
| 427 | 409 |
| 428 if (cg_image) { | 410 if (cg_image) { |
| 429 cursor_info.type = WebCursorInfo::TypeCustom; | 411 cursor_info.type = WebCursorInfo::TypeCustom; |
| 430 NSPoint hot_spot = [cursor hotSpot]; | 412 NSPoint hot_spot = [cursor hotSpot]; |
| 431 cursor_info.hotSpot = WebKit::WebPoint(hot_spot.x, hot_spot.y); | 413 cursor_info.hotSpot = WebKit::WebPoint(hot_spot.x, hot_spot.y); |
| 432 #if WEBKIT_USING_SKIA | |
| 433 cursor_info.customImage = gfx::CGImageToSkBitmap(cg_image); | 414 cursor_info.customImage = gfx::CGImageToSkBitmap(cg_image); |
| 434 #else | |
| 435 cursor_info.customImage = cg_image; | |
| 436 #endif | |
| 437 } else { | 415 } else { |
| 438 cursor_info.type = WebCursorInfo::TypePointer; | 416 cursor_info.type = WebCursorInfo::TypePointer; |
| 439 } | 417 } |
| 440 } | 418 } |
| 441 | 419 |
| 442 InitFromCursorInfo(cursor_info); | 420 InitFromCursorInfo(cursor_info); |
| 443 } | 421 } |
| 444 | 422 |
| 445 #if !WEBKIT_USING_SKIA | |
| 446 void WebCursor::SetCustomData(const WebImage& image) { | |
| 447 if (image.isNull()) | |
| 448 return; | |
| 449 | |
| 450 base::mac::ScopedCFTypeRef<CGColorSpaceRef> cg_color( | |
| 451 CGColorSpaceCreateDeviceRGB()); | |
| 452 | |
| 453 const WebSize& image_dimensions = image.size(); | |
| 454 int image_width = image_dimensions.width; | |
| 455 int image_height = image_dimensions.height; | |
| 456 | |
| 457 size_t size = image_height * image_width * 4; | |
| 458 custom_data_.resize(size); | |
| 459 custom_size_.set_width(image_width); | |
| 460 custom_size_.set_height(image_height); | |
| 461 | |
| 462 // These settings match up with the code in CreateCustomCursor() above; keep | |
| 463 // them in sync. | |
| 464 // TODO(avi): test to ensure that the flags here are correct for RGBA | |
| 465 base::mac::ScopedCFTypeRef<CGContextRef> context( | |
| 466 CGBitmapContextCreate(&custom_data_[0], | |
| 467 image_width, | |
| 468 image_height, | |
| 469 8, | |
| 470 image_width * 4, | |
| 471 cg_color.get(), | |
| 472 kCGImageAlphaPremultipliedLast | | |
| 473 kCGBitmapByteOrder32Big)); | |
| 474 CGRect rect = CGRectMake(0, 0, image_width, image_height); | |
| 475 CGContextDrawImage(context.get(), rect, image.getCGImageRef()); | |
| 476 } | |
| 477 | |
| 478 void WebCursor::ImageFromCustomData(WebImage* image) const { | |
| 479 if (custom_data_.empty()) | |
| 480 return; | |
| 481 | |
| 482 base::mac::ScopedCFTypeRef<CGImageRef> cg_image( | |
| 483 CreateCGImageFromCustomData(custom_data_, custom_size_)); | |
| 484 *image = cg_image.get(); | |
| 485 } | |
| 486 #endif // !WEBKIT_USING_SKIA | |
| 487 | |
| 488 void WebCursor::InitPlatformData() { | 423 void WebCursor::InitPlatformData() { |
| 489 return; | 424 return; |
| 490 } | 425 } |
| 491 | 426 |
| 492 bool WebCursor::SerializePlatformData(Pickle* pickle) const { | 427 bool WebCursor::SerializePlatformData(Pickle* pickle) const { |
| 493 return true; | 428 return true; |
| 494 } | 429 } |
| 495 | 430 |
| 496 bool WebCursor::DeserializePlatformData(PickleIterator* iter) { | 431 bool WebCursor::DeserializePlatformData(PickleIterator* iter) { |
| 497 return true; | 432 return true; |
| 498 } | 433 } |
| 499 | 434 |
| 500 bool WebCursor::IsPlatformDataEqual(const WebCursor& other) const { | 435 bool WebCursor::IsPlatformDataEqual(const WebCursor& other) const { |
| 501 return true; | 436 return true; |
| 502 } | 437 } |
| 503 | 438 |
| 504 void WebCursor::CleanupPlatformData() { | 439 void WebCursor::CleanupPlatformData() { |
| 505 return; | 440 return; |
| 506 } | 441 } |
| 507 | 442 |
| 508 void WebCursor::CopyPlatformData(const WebCursor& other) { | 443 void WebCursor::CopyPlatformData(const WebCursor& other) { |
| 509 return; | 444 return; |
| 510 } | 445 } |
| OLD | NEW |