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