d1c5d2ede2cca32ac8127b791fd7b07ac8a86435
[WebKit-https.git] / Source / WebCore / platform / Cursor.cpp
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
33 IntPoint determineHotSpot(Image* image, const IntPoint& specifiedHotSpot)
34 {
35     if (image->isNull())
36         return IntPoint();
37
38     // Hot spot must be inside cursor rectangle.
39     IntRect imageRect = image->rect();
40     if (imageRect.contains(specifiedHotSpot))
41         return specifiedHotSpot;
42
43     // If hot spot is not specified externally, it can be extracted from some image formats (e.g. .cur).
44     IntPoint intrinsicHotSpot;
45     bool imageHasIntrinsicHotSpot = image->getHotSpot(intrinsicHotSpot);
46     if (imageHasIntrinsicHotSpot && imageRect.contains(intrinsicHotSpot))
47         return intrinsicHotSpot;
48
49     return IntPoint();
50 }
51
52 const Cursor& Cursor::fromType(Cursor::Type type)
53 {
54     switch (type) {
55     case Cursor::Pointer:
56         return pointerCursor();
57     case Cursor::Cross:
58         return crossCursor();
59     case Cursor::Hand:
60         return handCursor();
61     case Cursor::IBeam:
62         return iBeamCursor();
63     case Cursor::Wait:
64         return waitCursor();
65     case Cursor::Help:
66         return helpCursor();
67     case Cursor::EastResize:
68         return eastResizeCursor();
69     case Cursor::NorthResize:
70         return northResizeCursor();
71     case Cursor::NorthEastResize:
72         return northEastResizeCursor();
73     case Cursor::NorthWestResize:
74         return northWestResizeCursor();
75     case Cursor::SouthResize:
76         return southResizeCursor();
77     case Cursor::SouthEastResize:
78         return southEastResizeCursor();
79     case Cursor::SouthWestResize:
80         return southWestResizeCursor();
81     case Cursor::WestResize:
82         return westResizeCursor();
83     case Cursor::NorthSouthResize:
84         return northSouthResizeCursor();
85     case Cursor::EastWestResize:
86         return eastWestResizeCursor();
87     case Cursor::NorthEastSouthWestResize:
88         return northEastSouthWestResizeCursor();
89     case Cursor::NorthWestSouthEastResize:
90         return northWestSouthEastResizeCursor();
91     case Cursor::ColumnResize:
92         return columnResizeCursor();
93     case Cursor::RowResize:
94         return rowResizeCursor();
95     case Cursor::MiddlePanning:
96         return middlePanningCursor();
97     case Cursor::EastPanning:
98         return eastPanningCursor();
99     case Cursor::NorthPanning:
100         return northPanningCursor();
101     case Cursor::NorthEastPanning:
102         return northEastPanningCursor();
103     case Cursor::NorthWestPanning:
104         return northWestPanningCursor();
105     case Cursor::SouthPanning:
106         return southPanningCursor();
107     case Cursor::SouthEastPanning:
108         return southEastPanningCursor();
109     case Cursor::SouthWestPanning:
110         return southWestPanningCursor();
111     case Cursor::WestPanning:
112         return westPanningCursor();
113     case Cursor::Move:
114         return moveCursor();
115     case Cursor::VerticalText:
116         return verticalTextCursor();
117     case Cursor::Cell:
118         return cellCursor();
119     case Cursor::ContextMenu:
120         return contextMenuCursor();
121     case Cursor::Alias:
122         return aliasCursor();
123     case Cursor::Progress:
124         return progressCursor();
125     case Cursor::NoDrop:
126         return noDropCursor();
127     case Cursor::Copy:
128         return copyCursor();
129     case Cursor::None:
130         return noneCursor();
131     case Cursor::NotAllowed:
132         return notAllowedCursor();
133     case Cursor::ZoomIn:
134         return zoomInCursor();
135     case Cursor::ZoomOut:
136         return zoomOutCursor();
137     case Cursor::Grab:
138         return grabCursor();
139     case Cursor::Grabbing:
140         return grabbingCursor();
141     case Cursor::Custom:
142         ASSERT_NOT_REACHED();
143     }
144     return pointerCursor();
145 }
146
147 const char* nameForCursorType(Cursor::Type type)
148 {
149     switch (type) {
150     case Cursor::Pointer:
151         return "Pointer";
152     case Cursor::Cross:
153         return "Cross";
154     case Cursor::Hand:
155         return "Hand";
156     case Cursor::IBeam:
157         return "IBeam";
158     case Cursor::Wait:
159         return "Wait";
160     case Cursor::Help:
161         return "Help";
162     case Cursor::EastResize:
163         return "EastResize";
164     case Cursor::NorthResize:
165         return "NorthResize";
166     case Cursor::NorthEastResize:
167         return "NorthEastResize";
168     case Cursor::NorthWestResize:
169         return "NorthWestResize";
170     case Cursor::SouthResize:
171         return "SouthResize";
172     case Cursor::SouthEastResize:
173         return "SouthEastResize";
174     case Cursor::SouthWestResize:
175         return "SouthWestResize";
176     case Cursor::WestResize:
177         return "WestResize";
178     case Cursor::NorthSouthResize:
179         return "NorthSouthResize";
180     case Cursor::EastWestResize:
181         return "EastWestResize";
182     case Cursor::NorthEastSouthWestResize:
183         return "NorthEastSouthWestResize";
184     case Cursor::NorthWestSouthEastResize:
185         return "NorthWestSouthEastResize";
186     case Cursor::ColumnResize:
187         return "ColumnResize";
188     case Cursor::RowResize:
189         return "RowResize";
190     case Cursor::MiddlePanning:
191         return "MiddlePanning";
192     case Cursor::EastPanning:
193         return "EastPanning";
194     case Cursor::NorthPanning:
195         return "NorthPanning";
196     case Cursor::NorthEastPanning:
197         return "NorthEastPanning";
198     case Cursor::NorthWestPanning:
199         return "NorthWestPanning";
200     case Cursor::SouthPanning:
201         return "SouthPanning";
202     case Cursor::SouthEastPanning:
203         return "SouthEastPanning";
204     case Cursor::SouthWestPanning:
205         return "SouthWestPanning";
206     case Cursor::WestPanning:
207         return "WestPanning";
208     case Cursor::Move:
209         return "Move";
210     case Cursor::VerticalText:
211         return "VerticalText";
212     case Cursor::Cell:
213         return "Cell";
214     case Cursor::ContextMenu:
215         return "ContextMenu";
216     case Cursor::Alias:
217         return "Alias";
218     case Cursor::Progress:
219         return "Progress";
220     case Cursor::NoDrop:
221         return "NoDrop";
222     case Cursor::Copy:
223         return "Copy";
224     case Cursor::None:
225         return "None";
226     case Cursor::NotAllowed:
227         return "NotAllowed";
228     case Cursor::ZoomIn:
229         return "ZoomIn";
230     case Cursor::ZoomOut:
231         return "ZoomOut";
232     case Cursor::Grab:
233         return "Grab";
234     case Cursor::Grabbing:
235         return "Grabbing";
236     case Cursor::Custom:
237         return "Custom";
238     }
239
240     return "ERROR";
241 }
242
243 #if USE(LAZY_NATIVE_CURSOR)
244
245 Cursor::Cursor(Image* image, const IntPoint& hotSpot)
246     : m_type(Custom)
247     , m_image(image)
248     , m_hotSpot(determineHotSpot(image, hotSpot))
249     , m_platformCursor(0)
250 {
251 }
252
253 Cursor::Cursor(Type type)
254     : m_type(type)
255     , m_platformCursor(0)
256 {
257 }
258
259 #if !PLATFORM(MAC)
260
261 PlatformCursor Cursor::platformCursor() const
262 {
263     ensurePlatformCursor();
264     return m_platformCursor;
265 }
266
267 #endif
268
269 const Cursor& pointerCursor()
270 {
271     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Pointer));
272     return c;
273 }
274
275 const Cursor& crossCursor()
276 {
277     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Cross));
278     return c;
279 }
280
281 const Cursor& handCursor()
282 {
283     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Hand));
284     return c;
285 }
286
287 const Cursor& moveCursor()
288 {
289     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Move));
290     return c;
291 }
292
293 const Cursor& verticalTextCursor()
294 {
295     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::VerticalText));
296     return c;
297 }
298
299 const Cursor& cellCursor()
300 {
301     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Cell));
302     return c;
303 }
304
305 const Cursor& contextMenuCursor()
306 {
307     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::ContextMenu));
308     return c;
309 }
310
311 const Cursor& aliasCursor()
312 {
313     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Alias));
314     return c;
315 }
316
317 const Cursor& zoomInCursor()
318 {
319     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::ZoomIn));
320     return c;
321 }
322
323 const Cursor& zoomOutCursor()
324 {
325     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::ZoomOut));
326     return c;
327 }
328
329 const Cursor& copyCursor()
330 {
331     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Copy));
332     return c;
333 }
334
335 const Cursor& noneCursor()
336 {
337     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::None));
338     return c;
339 }
340
341 const Cursor& progressCursor()
342 {
343     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Progress));
344     return c;
345 }
346
347 const Cursor& noDropCursor()
348 {
349     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NoDrop));
350     return c;
351 }
352
353 const Cursor& notAllowedCursor()
354 {
355     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NotAllowed));
356     return c;
357 }
358
359 const Cursor& iBeamCursor()
360 {
361     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::IBeam));
362     return c;
363 }
364
365 const Cursor& waitCursor()
366 {
367     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Wait));
368     return c;
369 }
370
371 const Cursor& helpCursor()
372 {
373     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Help));
374     return c;
375 }
376
377 const Cursor& eastResizeCursor()
378 {
379     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::EastResize));
380     return c;
381 }
382
383 const Cursor& northResizeCursor()
384 {
385     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthResize));
386     return c;
387 }
388
389 const Cursor& northEastResizeCursor()
390 {
391     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthEastResize));
392     return c;
393 }
394
395 const Cursor& northWestResizeCursor()
396 {
397     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthWestResize));
398     return c;
399 }
400
401 const Cursor& southResizeCursor()
402 {
403     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::SouthResize));
404     return c;
405 }
406
407 const Cursor& southEastResizeCursor()
408 {
409     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::SouthEastResize));
410     return c;
411 }
412
413 const Cursor& southWestResizeCursor()
414 {
415     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::SouthWestResize));
416     return c;
417 }
418
419 const Cursor& westResizeCursor()
420 {
421     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::WestResize));
422     return c;
423 }
424
425 const Cursor& northSouthResizeCursor()
426 {
427     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthSouthResize));
428     return c;
429 }
430
431 const Cursor& eastWestResizeCursor()
432 {
433     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::EastWestResize));
434     return c;
435 }
436
437 const Cursor& northEastSouthWestResizeCursor()
438 {
439     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthEastSouthWestResize));
440     return c;
441 }
442
443 const Cursor& northWestSouthEastResizeCursor()
444 {
445     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthWestSouthEastResize));
446     return c;
447 }
448
449 const Cursor& columnResizeCursor()
450 {
451     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::ColumnResize));
452     return c;
453 }
454
455 const Cursor& rowResizeCursor()
456 {
457     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::RowResize));
458     return c;
459 }
460
461 const Cursor& middlePanningCursor()
462 {
463     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::MiddlePanning));
464     return c;
465 }
466     
467 const Cursor& eastPanningCursor()
468 {
469     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::EastPanning));
470     return c;
471 }
472     
473 const Cursor& northPanningCursor()
474 {
475     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthPanning));
476     return c;
477 }
478     
479 const Cursor& northEastPanningCursor()
480 {
481     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthEastPanning));
482     return c;
483 }
484     
485 const Cursor& northWestPanningCursor()
486 {
487     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthWestPanning));
488     return c;
489 }
490     
491 const Cursor& southPanningCursor()
492 {
493     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::SouthPanning));
494     return c;
495 }
496     
497 const Cursor& southEastPanningCursor()
498 {
499     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::SouthEastPanning));
500     return c;
501 }
502     
503 const Cursor& southWestPanningCursor()
504 {
505     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::SouthWestPanning));
506     return c;
507 }
508     
509 const Cursor& westPanningCursor()
510 {
511     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::WestPanning));
512     return c;
513 }
514
515 const Cursor& grabCursor()
516 {
517     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Grab));
518     return c;
519 }
520
521 const Cursor& grabbingCursor()
522 {
523     DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Grabbing));
524     return c;
525 }
526
527 #endif
528
529 } // namespace WebCore