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