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 | 8 |
9 #include "config.h" | 9 #include "base/logging.h" |
10 #include "PlatformCursor.h" | 10 #include "base/scoped_cftyperef.h" |
11 #include "RetainPtr.h" | 11 #include "webkit/api/public/WebCursorInfo.h" |
| 12 #include "webkit/api/public/WebImage.h" |
| 13 #include "webkit/api/public/WebSize.h" |
12 | 14 |
13 #undef LOG | 15 using WebKit::WebCursorInfo; |
14 #include "base/logging.h" | 16 using WebKit::WebImage; |
15 | 17 using WebKit::WebSize; |
16 using WebCore::PlatformCursor; | |
17 | 18 |
18 namespace { | 19 namespace { |
19 | 20 |
20 // TODO(avi): Is loading resources what we want to do here? | 21 // TODO(avi): Is loading resources what we want to do here? |
21 NSCursor* LoadCursor(const char* name, int x, int y) { | 22 NSCursor* LoadCursor(const char* name, int x, int y) { |
22 NSString* file_name = [NSString stringWithUTF8String:name]; | 23 NSString* file_name = [NSString stringWithUTF8String:name]; |
23 DCHECK(file_name); | 24 DCHECK(file_name); |
24 NSImage* cursor_image = [NSImage imageNamed:file_name]; | 25 NSImage* cursor_image = [NSImage imageNamed:file_name]; |
25 DCHECK(cursor_image); | 26 DCHECK(cursor_image); |
26 return [[[NSCursor alloc] initWithImage:cursor_image | 27 return [[[NSCursor alloc] initWithImage:cursor_image |
27 hotSpot:NSMakePoint(x, y)] autorelease]; | 28 hotSpot:NSMakePoint(x, y)] autorelease]; |
28 } | 29 } |
29 | 30 |
| 31 CGImageRef CreateCGImageFromCustomData(const std::vector<char>& custom_data, |
| 32 const gfx::Size& custom_size) { |
| 33 scoped_cftyperef<CGColorSpaceRef> cg_color(CGColorSpaceCreateDeviceRGB()); |
| 34 // this is safe since we're not going to draw into the context we're creating |
| 35 void* data = const_cast<char*>(&custom_data[0]); |
| 36 // settings here match SetCustomData() below; keep in sync |
| 37 scoped_cftyperef<CGContextRef> context( |
| 38 CGBitmapContextCreate(data, |
| 39 custom_size.width(), |
| 40 custom_size.height(), |
| 41 8, |
| 42 custom_size.width()*4, |
| 43 cg_color.get(), |
| 44 kCGImageAlphaPremultipliedLast | |
| 45 kCGBitmapByteOrder32Big)); |
| 46 return CGBitmapContextCreateImage(context.get()); |
| 47 } |
| 48 |
30 NSCursor* CreateCustomCursor(const std::vector<char>& custom_data, | 49 NSCursor* CreateCustomCursor(const std::vector<char>& custom_data, |
31 const gfx::Size& custom_size, | 50 const gfx::Size& custom_size, |
32 const gfx::Point& hotspot) { | 51 const gfx::Point& hotspot) { |
33 RetainPtr<CGColorSpace> cg_color(AdoptCF, CGColorSpaceCreateDeviceRGB()); | 52 scoped_cftyperef<CGImageRef> cg_image( |
34 // this is safe since we're not going to draw into the context we're creating | 53 CreateCGImageFromCustomData(custom_data, custom_size)); |
35 void* data = const_cast<void *>(static_cast<const void*>(&custom_data[0])); | |
36 // settings here match SetCustomData() below; keep in sync | |
37 RetainPtr<CGContextRef> context(AdoptCF, CGBitmapContextCreate( | |
38 data, | |
39 custom_size.width(), | |
40 custom_size.height(), | |
41 8, | |
42 custom_size.width()*4, | |
43 cg_color.get(), | |
44 kCGImageAlphaPremultipliedLast | | |
45 kCGBitmapByteOrder32Big)); | |
46 RetainPtr<CGImage> cg_image(AdoptCF, | |
47 CGBitmapContextCreateImage(context.get())); | |
48 | 54 |
49 RetainPtr<NSBitmapImageRep> ns_bitmap( | 55 NSBitmapImageRep* ns_bitmap = |
50 AdoptNS, [[NSBitmapImageRep alloc] initWithCGImage:cg_image.get()]); | 56 [[NSBitmapImageRep alloc] initWithCGImage:cg_image.get()]; |
51 RetainPtr<NSImage> cursor_image([[NSImage alloc] init]); | 57 NSImage* cursor_image = [[NSImage alloc] init]; |
52 [cursor_image.get() addRepresentation:ns_bitmap.get()]; | |
53 DCHECK(cursor_image); | 58 DCHECK(cursor_image); |
54 return [[[NSCursor alloc] initWithImage:cursor_image.get() | 59 [cursor_image addRepresentation:ns_bitmap]; |
55 hotSpot:NSMakePoint(hotspot.x(), | 60 [ns_bitmap release]; |
56 hotspot.y())] | 61 |
57 autorelease]; | 62 NSCursor* cursor = [[NSCursor alloc] initWithImage:cursor_image |
| 63 hotSpot:NSMakePoint(hotspot.x(), |
| 64 hotspot.y())]; |
| 65 [cursor_image release]; |
| 66 |
| 67 return [cursor autorelease]; |
58 } | 68 } |
59 | 69 |
60 } | 70 } // namespace |
61 | 71 |
62 // We're matching Safari's cursor choices; see platform/mac/CursorMac.mm | 72 // We're matching Safari's cursor choices; see platform/mac/CursorMac.mm |
63 NSCursor* WebCursor::GetCursor() const { | 73 NSCursor* WebCursor::GetCursor() const { |
64 switch (type_) { | 74 switch (type_) { |
65 case PlatformCursor::TypePointer: | 75 case WebCursorInfo::TypePointer: |
66 return [NSCursor arrowCursor]; | 76 return [NSCursor arrowCursor]; |
67 case PlatformCursor::TypeCross: | 77 case WebCursorInfo::TypeCross: |
68 return LoadCursor("crossHairCursor", 11, 11); | 78 return LoadCursor("crossHairCursor", 11, 11); |
69 case PlatformCursor::TypeHand: | 79 case WebCursorInfo::TypeHand: |
70 return LoadCursor("linkCursor", 6, 1); | 80 return LoadCursor("linkCursor", 6, 1); |
71 case PlatformCursor::TypeIBeam: | 81 case WebCursorInfo::TypeIBeam: |
72 return [NSCursor IBeamCursor]; | 82 return [NSCursor IBeamCursor]; |
73 case PlatformCursor::TypeWait: | 83 case WebCursorInfo::TypeWait: |
74 return LoadCursor("waitCursor", 7, 7); | 84 return LoadCursor("waitCursor", 7, 7); |
75 case PlatformCursor::TypeHelp: | 85 case WebCursorInfo::TypeHelp: |
76 return LoadCursor("helpCursor", 8, 8); | 86 return LoadCursor("helpCursor", 8, 8); |
77 case PlatformCursor::TypeEastResize: | 87 case WebCursorInfo::TypeEastResize: |
78 case PlatformCursor::TypeEastPanning: | 88 case WebCursorInfo::TypeEastPanning: |
79 return LoadCursor("eastResizeCursor", 14, 7); | 89 return LoadCursor("eastResizeCursor", 14, 7); |
80 case PlatformCursor::TypeNorthResize: | 90 case WebCursorInfo::TypeNorthResize: |
81 case PlatformCursor::TypeNorthPanning: | 91 case WebCursorInfo::TypeNorthPanning: |
82 return LoadCursor("northResizeCursor", 7, 1); | 92 return LoadCursor("northResizeCursor", 7, 1); |
83 case PlatformCursor::TypeNorthEastResize: | 93 case WebCursorInfo::TypeNorthEastResize: |
84 case PlatformCursor::TypeNorthEastPanning: | 94 case WebCursorInfo::TypeNorthEastPanning: |
85 return LoadCursor("northEastResizeCursor", 14, 1); | 95 return LoadCursor("northEastResizeCursor", 14, 1); |
86 case PlatformCursor::TypeNorthWestResize: | 96 case WebCursorInfo::TypeNorthWestResize: |
87 case PlatformCursor::TypeNorthWestPanning: | 97 case WebCursorInfo::TypeNorthWestPanning: |
88 return LoadCursor("northWestResizeCursor", 0, 0); | 98 return LoadCursor("northWestResizeCursor", 0, 0); |
89 case PlatformCursor::TypeSouthResize: | 99 case WebCursorInfo::TypeSouthResize: |
90 case PlatformCursor::TypeSouthPanning: | 100 case WebCursorInfo::TypeSouthPanning: |
91 return LoadCursor("southResizeCursor", 7, 14); | 101 return LoadCursor("southResizeCursor", 7, 14); |
92 case PlatformCursor::TypeSouthEastResize: | 102 case WebCursorInfo::TypeSouthEastResize: |
93 case PlatformCursor::TypeSouthEastPanning: | 103 case WebCursorInfo::TypeSouthEastPanning: |
94 return LoadCursor("southEastResizeCursor", 14, 14); | 104 return LoadCursor("southEastResizeCursor", 14, 14); |
95 case PlatformCursor::TypeSouthWestResize: | 105 case WebCursorInfo::TypeSouthWestResize: |
96 case PlatformCursor::TypeSouthWestPanning: | 106 case WebCursorInfo::TypeSouthWestPanning: |
97 return LoadCursor("southWestResizeCursor", 1, 14); | 107 return LoadCursor("southWestResizeCursor", 1, 14); |
98 case PlatformCursor::TypeWestResize: | 108 case WebCursorInfo::TypeWestResize: |
99 case PlatformCursor::TypeWestPanning: | 109 case WebCursorInfo::TypeWestPanning: |
100 return LoadCursor("westResizeCursor", 1, 7); | 110 return LoadCursor("westResizeCursor", 1, 7); |
101 case PlatformCursor::TypeNorthSouthResize: | 111 case WebCursorInfo::TypeNorthSouthResize: |
102 return LoadCursor("northSouthResizeCursor", 7, 7); | 112 return LoadCursor("northSouthResizeCursor", 7, 7); |
103 case PlatformCursor::TypeEastWestResize: | 113 case WebCursorInfo::TypeEastWestResize: |
104 return LoadCursor("eastWestResizeCursor", 7, 7); | 114 return LoadCursor("eastWestResizeCursor", 7, 7); |
105 case PlatformCursor::TypeNorthEastSouthWestResize: | 115 case WebCursorInfo::TypeNorthEastSouthWestResize: |
106 return LoadCursor("northEastSouthWestResizeCursor", 7, 7); | 116 return LoadCursor("northEastSouthWestResizeCursor", 7, 7); |
107 case PlatformCursor::TypeNorthWestSouthEastResize: | 117 case WebCursorInfo::TypeNorthWestSouthEastResize: |
108 return LoadCursor("northWestSouthEastResizeCursor", 7, 7); | 118 return LoadCursor("northWestSouthEastResizeCursor", 7, 7); |
109 case PlatformCursor::TypeColumnResize: | 119 case WebCursorInfo::TypeColumnResize: |
110 return [NSCursor resizeLeftRightCursor]; | 120 return [NSCursor resizeLeftRightCursor]; |
111 case PlatformCursor::TypeRowResize: | 121 case WebCursorInfo::TypeRowResize: |
112 return [NSCursor resizeUpDownCursor]; | 122 return [NSCursor resizeUpDownCursor]; |
113 case PlatformCursor::TypeMiddlePanning: | 123 case WebCursorInfo::TypeMiddlePanning: |
114 case PlatformCursor::TypeMove: | 124 case WebCursorInfo::TypeMove: |
115 return LoadCursor("moveCursor", 7, 7); | 125 return LoadCursor("moveCursor", 7, 7); |
116 case PlatformCursor::TypeVerticalText: | 126 case WebCursorInfo::TypeVerticalText: |
117 return LoadCursor("verticalTextCursor", 7, 7); | 127 return LoadCursor("verticalTextCursor", 7, 7); |
118 case PlatformCursor::TypeCell: | 128 case WebCursorInfo::TypeCell: |
119 return LoadCursor("cellCursor", 7, 7); | 129 return LoadCursor("cellCursor", 7, 7); |
120 case PlatformCursor::TypeContextMenu: | 130 case WebCursorInfo::TypeContextMenu: |
121 return LoadCursor("contextMenuCursor", 3, 2); | 131 return LoadCursor("contextMenuCursor", 3, 2); |
122 case PlatformCursor::TypeAlias: | 132 case WebCursorInfo::TypeAlias: |
123 return LoadCursor("aliasCursor", 11, 3); | 133 return LoadCursor("aliasCursor", 11, 3); |
124 case PlatformCursor::TypeProgress: | 134 case WebCursorInfo::TypeProgress: |
125 return LoadCursor("progressCursor", 3, 2); | 135 return LoadCursor("progressCursor", 3, 2); |
126 case PlatformCursor::TypeNoDrop: | 136 case WebCursorInfo::TypeNoDrop: |
127 return LoadCursor("noDropCursor", 3, 1); | 137 return LoadCursor("noDropCursor", 3, 1); |
128 case PlatformCursor::TypeCopy: | 138 case WebCursorInfo::TypeCopy: |
129 return LoadCursor("copyCursor", 3, 2); | 139 return LoadCursor("copyCursor", 3, 2); |
130 case PlatformCursor::TypeNone: | 140 case WebCursorInfo::TypeNone: |
131 return LoadCursor("noneCursor", 7, 7); | 141 return LoadCursor("noneCursor", 7, 7); |
132 case PlatformCursor::TypeNotAllowed: | 142 case WebCursorInfo::TypeNotAllowed: |
133 return LoadCursor("notAllowedCursor", 11, 11); | 143 return LoadCursor("notAllowedCursor", 11, 11); |
134 case PlatformCursor::TypeZoomIn: | 144 case WebCursorInfo::TypeZoomIn: |
135 return LoadCursor("zoomInCursor", 7, 7); | 145 return LoadCursor("zoomInCursor", 7, 7); |
136 case PlatformCursor::TypeZoomOut: | 146 case WebCursorInfo::TypeZoomOut: |
137 return LoadCursor("zoomOutCursor", 7, 7); | 147 return LoadCursor("zoomOutCursor", 7, 7); |
138 case PlatformCursor::TypeCustom: | 148 case WebCursorInfo::TypeCustom: |
139 return CreateCustomCursor(custom_data_, custom_size_, hotspot_); | 149 return CreateCustomCursor(custom_data_, custom_size_, hotspot_); |
140 } | 150 } |
141 NOTREACHED(); | 151 NOTREACHED(); |
142 return nil; | 152 return nil; |
143 } | 153 } |
144 | 154 |
145 void WebCursor::SetCustomData(WebCore::Image* image) { | 155 void WebCursor::SetCustomData(const WebImage& image) { |
146 WebCore::NativeImagePtr image_ptr = image->nativeImageForCurrentFrame(); | 156 if (image.isNull()) |
147 if (!image_ptr) | |
148 return; | 157 return; |
149 | 158 |
150 RetainPtr<CGColorSpace> cg_color(AdoptCF, CGColorSpaceCreateDeviceRGB()); | 159 scoped_cftyperef<CGColorSpaceRef> cg_color( |
| 160 CGColorSpaceCreateDeviceRGB()); |
151 | 161 |
152 size_t size = CGImageGetHeight(image_ptr)*CGImageGetWidth(image_ptr)*4; | 162 const WebSize& image_dimensions = image.size(); |
| 163 int image_width = image_dimensions.width; |
| 164 int image_height = image_dimensions.height; |
| 165 |
| 166 size_t size = image_height * image_width * 4; |
153 custom_data_.resize(size); | 167 custom_data_.resize(size); |
154 custom_size_.set_width(CGImageGetWidth(image_ptr)); | 168 custom_size_.set_width(image_width); |
155 custom_size_.set_height(CGImageGetHeight(image_ptr)); | 169 custom_size_.set_height(image_height); |
156 | 170 |
157 // These settings match up with the code in CreateCustomCursor() above; keep | 171 // These settings match up with the code in CreateCustomCursor() above; keep |
158 // them in sync. | 172 // them in sync. |
159 // TODO(avi): test to ensure that the flags here are correct for RGBA | 173 // TODO(avi): test to ensure that the flags here are correct for RGBA |
160 RetainPtr<CGContextRef> context(AdoptCF, CGBitmapContextCreate( | 174 scoped_cftyperef<CGContextRef> context( |
161 &custom_data_[0], | 175 CGBitmapContextCreate(&custom_data_[0], |
162 CGImageGetWidth(image_ptr), | 176 image_width, |
163 CGImageGetHeight(image_ptr), | 177 image_height, |
164 8, | 178 8, |
165 CGImageGetWidth(image_ptr)*4, | 179 image_width * 4, |
166 cg_color.get(), | 180 cg_color.get(), |
167 kCGImageAlphaPremultipliedLast | | 181 kCGImageAlphaPremultipliedLast | |
168 kCGBitmapByteOrder32Big)); | 182 kCGBitmapByteOrder32Big)); |
169 CGRect rect = CGRectMake(0, 0, | 183 CGRect rect = CGRectMake(0, 0, image_width, image_height); |
170 CGImageGetWidth(image_ptr), | 184 CGContextDrawImage(context.get(), rect, image.getCGImageRef()); |
171 CGImageGetHeight(image_ptr)); | 185 } |
172 CGContextDrawImage(context.get(), rect, image_ptr); | 186 |
| 187 void WebCursor::ImageFromCustomData(WebImage* image) const { |
| 188 if (custom_data_.empty()) |
| 189 return; |
| 190 |
| 191 scoped_cftyperef<CGImageRef> cg_image( |
| 192 CreateCGImageFromCustomData(custom_data_, custom_size_)); |
| 193 *image = cg_image.get(); |
173 } | 194 } |
174 | 195 |
175 void WebCursor::InitPlatformData() { | 196 void WebCursor::InitPlatformData() { |
176 return; | 197 return; |
177 } | 198 } |
178 | 199 |
179 bool WebCursor::SerializePlatformData(Pickle* pickle) const { | 200 bool WebCursor::SerializePlatformData(Pickle* pickle) const { |
180 return true; | 201 return true; |
181 } | 202 } |
182 | 203 |
183 bool WebCursor::DeserializePlatformData(const Pickle* pickle, void** iter) { | 204 bool WebCursor::DeserializePlatformData(const Pickle* pickle, void** iter) { |
184 return true; | 205 return true; |
185 } | 206 } |
186 | 207 |
187 bool WebCursor::IsPlatformDataEqual(const WebCursor& other) const { | 208 bool WebCursor::IsPlatformDataEqual(const WebCursor& other) const { |
188 return true; | 209 return true; |
189 } | 210 } |
190 | 211 |
191 void WebCursor::CleanupPlatformData() { | 212 void WebCursor::CleanupPlatformData() { |
192 return; | 213 return; |
193 } | 214 } |
194 | 215 |
195 void WebCursor::CopyPlatformData(const WebCursor& other) { | 216 void WebCursor::CopyPlatformData(const WebCursor& other) { |
196 return; | 217 return; |
197 } | 218 } |
OLD | NEW |