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