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
29 namespace WebCore {
30
determineHotSpot(Image * image,const IntPoint & specifiedHotSpot)31 IntPoint 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
fromType(Cursor::Type type)50 const 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
Cursor(Image * image,const IntPoint & hotSpot)145 Cursor::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
Cursor(Image * image,const IntPoint & hotSpot,float scale)153 Cursor::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
Cursor(Type type)161 Cursor::Cursor(Type type)
162 : m_type(type)
163 , m_imageScaleFactor(1)
164 {
165 }
166
Cursor(const Cursor & other)167 Cursor::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
operator =(const Cursor & other)175 Cursor& 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
~Cursor()184 Cursor::~Cursor()
185 {
186 }
187
pointerCursor()188 const Cursor& pointerCursor()
189 {
190 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Pointer));
191 return c;
192 }
193
crossCursor()194 const Cursor& crossCursor()
195 {
196 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Cross));
197 return c;
198 }
199
handCursor()200 const Cursor& handCursor()
201 {
202 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Hand));
203 return c;
204 }
205
moveCursor()206 const Cursor& moveCursor()
207 {
208 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Move));
209 return c;
210 }
211
verticalTextCursor()212 const Cursor& verticalTextCursor()
213 {
214 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::VerticalText));
215 return c;
216 }
217
cellCursor()218 const Cursor& cellCursor()
219 {
220 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Cell));
221 return c;
222 }
223
contextMenuCursor()224 const Cursor& contextMenuCursor()
225 {
226 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::ContextMenu));
227 return c;
228 }
229
aliasCursor()230 const Cursor& aliasCursor()
231 {
232 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Alias));
233 return c;
234 }
235
zoomInCursor()236 const Cursor& zoomInCursor()
237 {
238 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::ZoomIn));
239 return c;
240 }
241
zoomOutCursor()242 const Cursor& zoomOutCursor()
243 {
244 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::ZoomOut));
245 return c;
246 }
247
copyCursor()248 const Cursor& copyCursor()
249 {
250 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Copy));
251 return c;
252 }
253
noneCursor()254 const Cursor& noneCursor()
255 {
256 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::None));
257 return c;
258 }
259
progressCursor()260 const Cursor& progressCursor()
261 {
262 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Progress));
263 return c;
264 }
265
noDropCursor()266 const Cursor& noDropCursor()
267 {
268 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NoDrop));
269 return c;
270 }
271
notAllowedCursor()272 const Cursor& notAllowedCursor()
273 {
274 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NotAllowed));
275 return c;
276 }
277
iBeamCursor()278 const Cursor& iBeamCursor()
279 {
280 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::IBeam));
281 return c;
282 }
283
waitCursor()284 const Cursor& waitCursor()
285 {
286 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Wait));
287 return c;
288 }
289
helpCursor()290 const Cursor& helpCursor()
291 {
292 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Help));
293 return c;
294 }
295
eastResizeCursor()296 const Cursor& eastResizeCursor()
297 {
298 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::EastResize));
299 return c;
300 }
301
northResizeCursor()302 const Cursor& northResizeCursor()
303 {
304 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthResize));
305 return c;
306 }
307
northEastResizeCursor()308 const Cursor& northEastResizeCursor()
309 {
310 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthEastResize));
311 return c;
312 }
313
northWestResizeCursor()314 const Cursor& northWestResizeCursor()
315 {
316 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthWestResize));
317 return c;
318 }
319
southResizeCursor()320 const Cursor& southResizeCursor()
321 {
322 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::SouthResize));
323 return c;
324 }
325
southEastResizeCursor()326 const Cursor& southEastResizeCursor()
327 {
328 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::SouthEastResize));
329 return c;
330 }
331
southWestResizeCursor()332 const Cursor& southWestResizeCursor()
333 {
334 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::SouthWestResize));
335 return c;
336 }
337
westResizeCursor()338 const Cursor& westResizeCursor()
339 {
340 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::WestResize));
341 return c;
342 }
343
northSouthResizeCursor()344 const Cursor& northSouthResizeCursor()
345 {
346 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthSouthResize));
347 return c;
348 }
349
eastWestResizeCursor()350 const Cursor& eastWestResizeCursor()
351 {
352 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::EastWestResize));
353 return c;
354 }
355
northEastSouthWestResizeCursor()356 const Cursor& northEastSouthWestResizeCursor()
357 {
358 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthEastSouthWestResize));
359 return c;
360 }
361
northWestSouthEastResizeCursor()362 const Cursor& northWestSouthEastResizeCursor()
363 {
364 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthWestSouthEastResize));
365 return c;
366 }
367
columnResizeCursor()368 const Cursor& columnResizeCursor()
369 {
370 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::ColumnResize));
371 return c;
372 }
373
rowResizeCursor()374 const Cursor& rowResizeCursor()
375 {
376 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::RowResize));
377 return c;
378 }
379
middlePanningCursor()380 const Cursor& middlePanningCursor()
381 {
382 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::MiddlePanning));
383 return c;
384 }
385
eastPanningCursor()386 const Cursor& eastPanningCursor()
387 {
388 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::EastPanning));
389 return c;
390 }
391
northPanningCursor()392 const Cursor& northPanningCursor()
393 {
394 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthPanning));
395 return c;
396 }
397
northEastPanningCursor()398 const Cursor& northEastPanningCursor()
399 {
400 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthEastPanning));
401 return c;
402 }
403
northWestPanningCursor()404 const Cursor& northWestPanningCursor()
405 {
406 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::NorthWestPanning));
407 return c;
408 }
409
southPanningCursor()410 const Cursor& southPanningCursor()
411 {
412 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::SouthPanning));
413 return c;
414 }
415
southEastPanningCursor()416 const Cursor& southEastPanningCursor()
417 {
418 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::SouthEastPanning));
419 return c;
420 }
421
southWestPanningCursor()422 const Cursor& southWestPanningCursor()
423 {
424 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::SouthWestPanning));
425 return c;
426 }
427
westPanningCursor()428 const Cursor& westPanningCursor()
429 {
430 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::WestPanning));
431 return c;
432 }
433
grabCursor()434 const Cursor& grabCursor()
435 {
436 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Grab));
437 return c;
438 }
439
grabbingCursor()440 const Cursor& grabbingCursor()
441 {
442 DEFINE_STATIC_LOCAL(Cursor, c, (Cursor::Grabbing));
443 return c;
444 }
445
446 } // namespace WebCore
447