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