1 /**
2  * Copyright (c) 2006-2019 LOVE Development Team
3  *
4  * This software is provided 'as-is', without any express or implied
5  * warranty.  In no event will the authors be held liable for any damages
6  * arising from the use of this software.
7  *
8  * Permission is granted to anyone to use this software for any purpose,
9  * including commercial applications, and to alter it and redistribute it
10  * freely, subject to the following restrictions:
11  *
12  * 1. The origin of this software must not be misrepresented; you must not
13  *    claim that you wrote the original software. If you use this software
14  *    in a product, an acknowledgment in the product documentation would be
15  *    appreciated but is not required.
16  * 2. Altered source versions must be plainly marked as such, and must not be
17  *    misrepresented as being the original software.
18  * 3. This notice may not be removed or altered from any source distribution.
19  **/
20 
21 // LOVE
22 #include "Cursor.h"
23 #include "common/config.h"
24 
25 namespace love
26 {
27 namespace mouse
28 {
29 namespace sdl
30 {
31 
Cursor(image::ImageData * data,int hotx,int hoty)32 Cursor::Cursor(image::ImageData *data, int hotx, int hoty)
33 	: cursor(nullptr)
34 	, type(CURSORTYPE_IMAGE)
35 	, systemType(CURSOR_MAX_ENUM)
36 {
37 	Uint32 rmask, gmask, bmask, amask;
38 #ifdef LOVE_BIG_ENDIAN
39 	rmask = 0xFF000000;
40 	gmask = 0x00FF0000;
41 	bmask = 0x0000FF00;
42 	amask = 0x000000FF;
43 #else
44 	rmask = 0x000000FF;
45 	gmask = 0x0000FF00;
46 	bmask = 0x00FF0000;
47 	amask = 0xFF000000;
48 #endif
49 
50 	int w = data->getWidth();
51 	int h = data->getHeight();
52 	int pitch = w * 4;
53 
54 	SDL_Surface *surface = SDL_CreateRGBSurfaceFrom(data->getData(), w, h, 32, pitch, rmask, gmask, bmask, amask);
55 	if (!surface)
56 		throw love::Exception("Cannot create cursor: out of memory!");
57 
58 	cursor = SDL_CreateColorCursor(surface, hotx, hoty);
59 	SDL_FreeSurface(surface);
60 
61 	if (!cursor)
62 		throw love::Exception("Cannot create cursor: %s", SDL_GetError());
63 }
64 
Cursor(mouse::Cursor::SystemCursor cursortype)65 Cursor::Cursor(mouse::Cursor::SystemCursor cursortype)
66 	: cursor(nullptr)
67 	, type(CURSORTYPE_SYSTEM)
68 	, systemType(cursortype)
69 {
70 	SDL_SystemCursor sdlcursortype;
71 
72 	if (systemCursors.find(cursortype, sdlcursortype))
73 		cursor = SDL_CreateSystemCursor(sdlcursortype);
74 	else
75 		throw love::Exception("Cannot create system cursor: invalid type.");
76 
77 	if (!cursor)
78 		throw love::Exception("Cannot create system cursor: %s", SDL_GetError());
79 }
80 
~Cursor()81 Cursor::~Cursor()
82 {
83 	if (cursor)
84 		SDL_FreeCursor(cursor);
85 }
86 
getHandle() const87 void *Cursor::getHandle() const
88 {
89 	return cursor;
90 }
91 
getType() const92 Cursor::CursorType Cursor::getType() const
93 {
94 	return type;
95 }
96 
getSystemType() const97 Cursor::SystemCursor Cursor::getSystemType() const
98 {
99 	return systemType;
100 }
101 
102 EnumMap<Cursor::SystemCursor, SDL_SystemCursor, Cursor::CURSOR_MAX_ENUM>::Entry Cursor::systemCursorEntries[] =
103 {
104 	{Cursor::CURSOR_ARROW, SDL_SYSTEM_CURSOR_ARROW},
105 	{Cursor::CURSOR_IBEAM, SDL_SYSTEM_CURSOR_IBEAM},
106 	{Cursor::CURSOR_WAIT, SDL_SYSTEM_CURSOR_WAIT},
107 	{Cursor::CURSOR_CROSSHAIR, SDL_SYSTEM_CURSOR_CROSSHAIR},
108 	{Cursor::CURSOR_WAITARROW, SDL_SYSTEM_CURSOR_WAITARROW},
109 	{Cursor::CURSOR_SIZENWSE, SDL_SYSTEM_CURSOR_SIZENWSE},
110 	{Cursor::CURSOR_SIZENESW, SDL_SYSTEM_CURSOR_SIZENESW},
111 	{Cursor::CURSOR_SIZEWE, SDL_SYSTEM_CURSOR_SIZEWE},
112 	{Cursor::CURSOR_SIZENS, SDL_SYSTEM_CURSOR_SIZENS},
113 	{Cursor::CURSOR_SIZEALL, SDL_SYSTEM_CURSOR_SIZEALL},
114 	{Cursor::CURSOR_NO, SDL_SYSTEM_CURSOR_NO},
115 	{Cursor::CURSOR_HAND, SDL_SYSTEM_CURSOR_HAND},
116 };
117 
118 EnumMap<Cursor::SystemCursor, SDL_SystemCursor, Cursor::CURSOR_MAX_ENUM> Cursor::systemCursors(Cursor::systemCursorEntries, sizeof(Cursor::systemCursorEntries));
119 
120 } // sdl
121 } // mouse
122 } // love
123