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
31namespace WebCore {
32
33IntPoint 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
49const 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
144const 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
242Cursor::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
250Cursor::Cursor(Type type)
251    : m_type(type)
252    , m_platformCursor(0)
253{
254}
255
256#if !PLATFORM(MAC)
257
258PlatformCursor Cursor::platformCursor() const
259{
260    ensurePlatformCursor();
261    return m_platformCursor;
262}
263
264#endif
265
266const Cursor& pointerCursor()
267{
268    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Pointer));
269    return c;
270}
271
272const Cursor& crossCursor()
273{
274    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Cross));
275    return c;
276}
277
278const Cursor& handCursor()
279{
280    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Hand));
281    return c;
282}
283
284const Cursor& moveCursor()
285{
286    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Move));
287    return c;
288}
289
290const Cursor& verticalTextCursor()
291{
292    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::VerticalText));
293    return c;
294}
295
296const Cursor& cellCursor()
297{
298    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Cell));
299    return c;
300}
301
302const Cursor& contextMenuCursor()
303{
304    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::ContextMenu));
305    return c;
306}
307
308const Cursor& aliasCursor()
309{
310    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Alias));
311    return c;
312}
313
314const Cursor& zoomInCursor()
315{
316    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::ZoomIn));
317    return c;
318}
319
320const Cursor& zoomOutCursor()
321{
322    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::ZoomOut));
323    return c;
324}
325
326const Cursor& copyCursor()
327{
328    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Copy));
329    return c;
330}
331
332const Cursor& noneCursor()
333{
334    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::None));
335    return c;
336}
337
338const Cursor& progressCursor()
339{
340    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Progress));
341    return c;
342}
343
344const Cursor& noDropCursor()
345{
346    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NoDrop));
347    return c;
348}
349
350const Cursor& notAllowedCursor()
351{
352    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NotAllowed));
353    return c;
354}
355
356const Cursor& iBeamCursor()
357{
358    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::IBeam));
359    return c;
360}
361
362const Cursor& waitCursor()
363{
364    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Wait));
365    return c;
366}
367
368const Cursor& helpCursor()
369{
370    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Help));
371    return c;
372}
373
374const Cursor& eastResizeCursor()
375{
376    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::EastResize));
377    return c;
378}
379
380const Cursor& northResizeCursor()
381{
382    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthResize));
383    return c;
384}
385
386const Cursor& northEastResizeCursor()
387{
388    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthEastResize));
389    return c;
390}
391
392const Cursor& northWestResizeCursor()
393{
394    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthWestResize));
395    return c;
396}
397
398const Cursor& southResizeCursor()
399{
400    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::SouthResize));
401    return c;
402}
403
404const Cursor& southEastResizeCursor()
405{
406    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::SouthEastResize));
407    return c;
408}
409
410const Cursor& southWestResizeCursor()
411{
412    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::SouthWestResize));
413    return c;
414}
415
416const Cursor& westResizeCursor()
417{
418    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::WestResize));
419    return c;
420}
421
422const Cursor& northSouthResizeCursor()
423{
424    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthSouthResize));
425    return c;
426}
427
428const Cursor& eastWestResizeCursor()
429{
430    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::EastWestResize));
431    return c;
432}
433
434const Cursor& northEastSouthWestResizeCursor()
435{
436    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthEastSouthWestResize));
437    return c;
438}
439
440const Cursor& northWestSouthEastResizeCursor()
441{
442    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthWestSouthEastResize));
443    return c;
444}
445
446const Cursor& columnResizeCursor()
447{
448    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::ColumnResize));
449    return c;
450}
451
452const Cursor& rowResizeCursor()
453{
454    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::RowResize));
455    return c;
456}
457
458const Cursor& middlePanningCursor()
459{
460    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::MiddlePanning));
461    return c;
462}
463
464const Cursor& eastPanningCursor()
465{
466    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::EastPanning));
467    return c;
468}
469
470const Cursor& northPanningCursor()
471{
472    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthPanning));
473    return c;
474}
475
476const Cursor& northEastPanningCursor()
477{
478    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthEastPanning));
479    return c;
480}
481
482const Cursor& northWestPanningCursor()
483{
484    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthWestPanning));
485    return c;
486}
487
488const Cursor& southPanningCursor()
489{
490    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::SouthPanning));
491    return c;
492}
493
494const Cursor& southEastPanningCursor()
495{
496    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::SouthEastPanning));
497    return c;
498}
499
500const Cursor& southWestPanningCursor()
501{
502    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::SouthWestPanning));
503    return c;
504}
505
506const Cursor& westPanningCursor()
507{
508    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::WestPanning));
509    return c;
510}
511
512const Cursor& grabCursor()
513{
514    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Grab));
515    return c;
516}
517
518const Cursor& grabbingCursor()
519{
520    DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Grabbing));
521    return c;
522}
523
524#endif
525
526} // namespace WebCore
527