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 |