1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "config.h"
27 #include "Cursor.h"
28 
29 #include "Image.h"
30 
31 namespace WebCore {
32 
determineHotSpot(Image * image,const IntPoint & specifiedHotSpot)33 IntPoint determineHotSpot(Image* image, const IntPoint& specifiedHotSpot)
34 {
35     // Hot spot must be inside cursor rectangle.
36     IntRect imageRect = image->rect();
37     if (imageRect.contains(specifiedHotSpot))
38         return specifiedHotSpot;
39 
40     // If hot spot is not specified externally, it can be extracted from some image formats (e.g. .cur).
41     IntPoint intrinsicHotSpot;
42     bool imageHasIntrinsicHotSpot = image->getHotSpot(intrinsicHotSpot);
43     if (imageHasIntrinsicHotSpot && imageRect.contains(intrinsicHotSpot))
44         return intrinsicHotSpot;
45 
46     return IntPoint();
47 }
48 
fromType(Cursor::Type type)49 const Cursor& Cursor::fromType(Cursor::Type type)
50 {
51     switch (type) {
52     case Cursor::Pointer:
53         return pointerCursor();
54     case Cursor::Cross:
55         return crossCursor();
56     case Cursor::Hand:
57         return handCursor();
58     case Cursor::IBeam:
59         return iBeamCursor();
60     case Cursor::Wait:
61         return waitCursor();
62     case Cursor::Help:
63         return helpCursor();
64     case Cursor::EastResize:
65         return eastResizeCursor();
66     case Cursor::NorthResize:
67         return northResizeCursor();
68     case Cursor::NorthEastResize:
69         return northEastResizeCursor();
70     case Cursor::NorthWestResize:
71         return northWestResizeCursor();
72     case Cursor::SouthResize:
73         return southResizeCursor();
74     case Cursor::SouthEastResize:
75         return southEastResizeCursor();
76     case Cursor::SouthWestResize:
77         return southWestResizeCursor();
78     case Cursor::WestResize:
79         return westResizeCursor();
80     case Cursor::NorthSouthResize:
81         return northSouthResizeCursor();
82     case Cursor::EastWestResize:
83         return eastWestResizeCursor();
84     case Cursor::NorthEastSouthWestResize:
85         return northEastSouthWestResizeCursor();
86     case Cursor::NorthWestSouthEastResize:
87         return northWestSouthEastResizeCursor();
88     case Cursor::ColumnResize:
89         return columnResizeCursor();
90     case Cursor::RowResize:
91         return rowResizeCursor();
92     case Cursor::MiddlePanning:
93         return middlePanningCursor();
94     case Cursor::EastPanning:
95         return eastPanningCursor();
96     case Cursor::NorthPanning:
97         return northPanningCursor();
98     case Cursor::NorthEastPanning:
99         return northEastPanningCursor();
100     case Cursor::NorthWestPanning:
101         return northWestPanningCursor();
102     case Cursor::SouthPanning:
103         return southPanningCursor();
104     case Cursor::SouthEastPanning:
105         return southEastPanningCursor();
106     case Cursor::SouthWestPanning:
107         return southWestPanningCursor();
108     case Cursor::WestPanning:
109         return westPanningCursor();
110     case Cursor::Move:
111         return moveCursor();
112     case Cursor::VerticalText:
113         return verticalTextCursor();
114     case Cursor::Cell:
115         return cellCursor();
116     case Cursor::ContextMenu:
117         return contextMenuCursor();
118     case Cursor::Alias:
119         return aliasCursor();
120     case Cursor::Progress:
121         return progressCursor();
122     case Cursor::NoDrop:
123         return noDropCursor();
124     case Cursor::Copy:
125         return copyCursor();
126     case Cursor::None:
127         return noneCursor();
128     case Cursor::NotAllowed:
129         return notAllowedCursor();
130     case Cursor::ZoomIn:
131         return zoomInCursor();
132     case Cursor::ZoomOut:
133         return zoomOutCursor();
134     case Cursor::Grab:
135         return grabCursor();
136     case Cursor::Grabbing:
137         return grabbingCursor();
138     case Cursor::Custom:
139         ASSERT_NOT_REACHED();
140     }
141     return pointerCursor();
142 }
143 
nameForCursorType(Cursor::Type type)144 const char* nameForCursorType(Cursor::Type type)
145 {
146     switch (type) {
147     case Cursor::Pointer:
148         return "Pointer";
149     case Cursor::Cross:
150         return "Cross";
151     case Cursor::Hand:
152         return "Hand";
153     case Cursor::IBeam:
154         return "IBeam";
155     case Cursor::Wait:
156         return "Wait";
157     case Cursor::Help:
158         return "Help";
159     case Cursor::EastResize:
160         return "EastResize";
161     case Cursor::NorthResize:
162         return "NorthResize";
163     case Cursor::NorthEastResize:
164         return "NorthEastResize";
165     case Cursor::NorthWestResize:
166         return "NorthWestResize";
167     case Cursor::SouthResize:
168         return "SouthResize";
169     case Cursor::SouthEastResize:
170         return "SouthEastResize";
171     case Cursor::SouthWestResize:
172         return "SouthWestResize";
173     case Cursor::WestResize:
174         return "WestResize";
175     case Cursor::NorthSouthResize:
176         return "NorthSouthResize";
177     case Cursor::EastWestResize:
178         return "EastWestResize";
179     case Cursor::NorthEastSouthWestResize:
180         return "NorthEastSouthWestResize";
181     case Cursor::NorthWestSouthEastResize:
182         return "NorthWestSouthEastResize";
183     case Cursor::ColumnResize:
184         return "ColumnResize";
185     case Cursor::RowResize:
186         return "RowResize";
187     case Cursor::MiddlePanning:
188         return "MiddlePanning";
189     case Cursor::EastPanning:
190         return "EastPanning";
191     case Cursor::NorthPanning:
192         return "NorthPanning";
193     case Cursor::NorthEastPanning:
194         return "NorthEastPanning";
195     case Cursor::NorthWestPanning:
196         return "NorthWestPanning";
197     case Cursor::SouthPanning:
198         return "SouthPanning";
199     case Cursor::SouthEastPanning:
200         return "SouthEastPanning";
201     case Cursor::SouthWestPanning:
202         return "SouthWestPanning";
203     case Cursor::WestPanning:
204         return "WestPanning";
205     case Cursor::Move:
206         return "Move";
207     case Cursor::VerticalText:
208         return "VerticalText";
209     case Cursor::Cell:
210         return "Cell";
211     case Cursor::ContextMenu:
212         return "ContextMenu";
213     case Cursor::Alias:
214         return "Alias";
215     case Cursor::Progress:
216         return "Progress";
217     case Cursor::NoDrop:
218         return "NoDrop";
219     case Cursor::Copy:
220         return "Copy";
221     case Cursor::None:
222         return "None";
223     case Cursor::NotAllowed:
224         return "NotAllowed";
225     case Cursor::ZoomIn:
226         return "ZoomIn";
227     case Cursor::ZoomOut:
228         return "ZoomOut";
229     case Cursor::Grab:
230         return "Grab";
231     case Cursor::Grabbing:
232         return "Grabbing";
233     case Cursor::Custom:
234         return "Custom";
235     }
236 
237     return "ERROR";
238 }
239 
240 #if USE(LAZY_NATIVE_CURSOR)
241 
Cursor(Image * image,const IntPoint & hotSpot)242 Cursor::Cursor(Image* image, const IntPoint& hotSpot)
243     : m_type(Custom)
244     , m_image(image)
245     , m_hotSpot(determineHotSpot(image, hotSpot))
246     , m_platformCursor(0)
247 {
248 }
249 
Cursor(Type type)250 Cursor::Cursor(Type type)
251     : m_type(type)
252     , m_platformCursor(0)
253 {
254 }
255 
256 #if !PLATFORM(MAC)
257 
platformCursor() const258 PlatformCursor Cursor::platformCursor() const
259 {
260     ensurePlatformCursor();
261     return m_platformCursor;
262 }
263 
264 #endif
265 
pointerCursor()266 const Cursor& pointerCursor()
267 {
268     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Pointer));
269     return c;
270 }
271 
crossCursor()272 const Cursor& crossCursor()
273 {
274     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Cross));
275     return c;
276 }
277 
handCursor()278 const Cursor& handCursor()
279 {
280     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Hand));
281     return c;
282 }
283 
moveCursor()284 const Cursor& moveCursor()
285 {
286     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Move));
287     return c;
288 }
289 
verticalTextCursor()290 const Cursor& verticalTextCursor()
291 {
292     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::VerticalText));
293     return c;
294 }
295 
cellCursor()296 const Cursor& cellCursor()
297 {
298     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Cell));
299     return c;
300 }
301 
contextMenuCursor()302 const Cursor& contextMenuCursor()
303 {
304     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::ContextMenu));
305     return c;
306 }
307 
aliasCursor()308 const Cursor& aliasCursor()
309 {
310     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Alias));
311     return c;
312 }
313 
zoomInCursor()314 const Cursor& zoomInCursor()
315 {
316     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::ZoomIn));
317     return c;
318 }
319 
zoomOutCursor()320 const Cursor& zoomOutCursor()
321 {
322     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::ZoomOut));
323     return c;
324 }
325 
copyCursor()326 const Cursor& copyCursor()
327 {
328     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Copy));
329     return c;
330 }
331 
noneCursor()332 const Cursor& noneCursor()
333 {
334     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::None));
335     return c;
336 }
337 
progressCursor()338 const Cursor& progressCursor()
339 {
340     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Progress));
341     return c;
342 }
343 
noDropCursor()344 const Cursor& noDropCursor()
345 {
346     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NoDrop));
347     return c;
348 }
349 
notAllowedCursor()350 const Cursor& notAllowedCursor()
351 {
352     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NotAllowed));
353     return c;
354 }
355 
iBeamCursor()356 const Cursor& iBeamCursor()
357 {
358     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::IBeam));
359     return c;
360 }
361 
waitCursor()362 const Cursor& waitCursor()
363 {
364     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Wait));
365     return c;
366 }
367 
helpCursor()368 const Cursor& helpCursor()
369 {
370     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Help));
371     return c;
372 }
373 
eastResizeCursor()374 const Cursor& eastResizeCursor()
375 {
376     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::EastResize));
377     return c;
378 }
379 
northResizeCursor()380 const Cursor& northResizeCursor()
381 {
382     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthResize));
383     return c;
384 }
385 
northEastResizeCursor()386 const Cursor& northEastResizeCursor()
387 {
388     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthEastResize));
389     return c;
390 }
391 
northWestResizeCursor()392 const Cursor& northWestResizeCursor()
393 {
394     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthWestResize));
395     return c;
396 }
397 
southResizeCursor()398 const Cursor& southResizeCursor()
399 {
400     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::SouthResize));
401     return c;
402 }
403 
southEastResizeCursor()404 const Cursor& southEastResizeCursor()
405 {
406     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::SouthEastResize));
407     return c;
408 }
409 
southWestResizeCursor()410 const Cursor& southWestResizeCursor()
411 {
412     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::SouthWestResize));
413     return c;
414 }
415 
westResizeCursor()416 const Cursor& westResizeCursor()
417 {
418     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::WestResize));
419     return c;
420 }
421 
northSouthResizeCursor()422 const Cursor& northSouthResizeCursor()
423 {
424     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthSouthResize));
425     return c;
426 }
427 
eastWestResizeCursor()428 const Cursor& eastWestResizeCursor()
429 {
430     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::EastWestResize));
431     return c;
432 }
433 
northEastSouthWestResizeCursor()434 const Cursor& northEastSouthWestResizeCursor()
435 {
436     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthEastSouthWestResize));
437     return c;
438 }
439 
northWestSouthEastResizeCursor()440 const Cursor& northWestSouthEastResizeCursor()
441 {
442     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthWestSouthEastResize));
443     return c;
444 }
445 
columnResizeCursor()446 const Cursor& columnResizeCursor()
447 {
448     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::ColumnResize));
449     return c;
450 }
451 
rowResizeCursor()452 const Cursor& rowResizeCursor()
453 {
454     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::RowResize));
455     return c;
456 }
457 
middlePanningCursor()458 const Cursor& middlePanningCursor()
459 {
460     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::MiddlePanning));
461     return c;
462 }
463 
eastPanningCursor()464 const Cursor& eastPanningCursor()
465 {
466     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::EastPanning));
467     return c;
468 }
469 
northPanningCursor()470 const Cursor& northPanningCursor()
471 {
472     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthPanning));
473     return c;
474 }
475 
northEastPanningCursor()476 const Cursor& northEastPanningCursor()
477 {
478     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthEastPanning));
479     return c;
480 }
481 
northWestPanningCursor()482 const Cursor& northWestPanningCursor()
483 {
484     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthWestPanning));
485     return c;
486 }
487 
southPanningCursor()488 const Cursor& southPanningCursor()
489 {
490     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::SouthPanning));
491     return c;
492 }
493 
southEastPanningCursor()494 const Cursor& southEastPanningCursor()
495 {
496     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::SouthEastPanning));
497     return c;
498 }
499 
southWestPanningCursor()500 const Cursor& southWestPanningCursor()
501 {
502     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::SouthWestPanning));
503     return c;
504 }
505 
westPanningCursor()506 const Cursor& westPanningCursor()
507 {
508     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::WestPanning));
509     return c;
510 }
511 
grabCursor()512 const Cursor& grabCursor()
513 {
514     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Grab));
515     return c;
516 }
517 
grabbingCursor()518 const Cursor& grabbingCursor()
519 {
520     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Grabbing));
521     return c;
522 }
523 
524 #endif
525 
526 } // namespace WebCore
527