1 /*
2  *  Copyright (C) 2004 Tom Bradley
3  *  tojabr@shiftygames.com
4  *
5  *  initCursor function by Anonymous from man SDL_CreateCursor
6  *
7  *  file: pointer.c
8  *
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2, or (at your option)
12  *  any later version.
13  *
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software Foundation,
21  *  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22  *
23  */
24 
25 #include <stdlib.h>
26 
27 #include "SDL_image.h"
28 #include "SDL.h"
29 
30 #include "pointer.h"
31 
32 static SDL_Cursor * handCursor  = 0;
33 static SDL_Cursor * arrowCursor = 0;
34 
35 static const char * hand[] = {
36 	"32 32 3 1",
37 	"x c #000000",
38 	". c #ffffff",
39 	"  c None",
40 	"     xx                         ",
41 	"    x..x                        ",
42 	"    x..x                        ",
43 	"    x..x                        ",
44 	"    x..xxx x                    ",
45 	"    x..x..x.xx                  ",
46 	" xx x..x..x.x.x                 ",
47 	"x..xx.........x                 ",
48 	"x...x.........x                 ",
49 	" x.....x.x.x..x                 ",
50 	"  x....x.x.x..x                 ",
51 	"  x....x.x.x.x                  ",
52 	"   x.........x                  ",
53 	"    x.......x                   ",
54 	"     x....x.x                   ",
55 	"      xxxx x                    ",
56 	"                                ",
57 	"                                ",
58 	"                                ",
59 	"                                ",
60 	"                                ",
61 	"                                ",
62 	"                                ",
63 	"                                ",
64 	"                                ",
65 	"                                ",
66 	"                                ",
67 	"                                ",
68 	"                                ",
69 	"                                ",
70 	"                                ",
71 	"                                ",
72 	"0,0"
73 };
74 
75 static const char * arrow[] = {
76 	"32 32 3 1",
77 	"x c #000000",
78 	". c #ffffff",
79 	"  c None",
80 	".                               ",
81 	"..                              ",
82 	".x.                             ",
83 	".xx.                            ",
84 	".xxx.                           ",
85 	".xxxx.                          ",
86 	".xxxxx.                         ",
87 	".xxxxxx.                        ",
88 	".xxxxxxx.                       ",
89 	".xxxxxxxx.                      ",
90 	".xxxxx.....                     ",
91 	".xx.xx.                         ",
92 	".x. .xx.                        ",
93 	"..  .xx.                        ",
94 	".    .xx.                       ",
95 	"     .xx.                       ",
96 	"      .x..                      ",
97 	"      ...                       ",
98 	"                                ",
99 	"                                ",
100 	"                                ",
101 	"                                ",
102 	"                                ",
103 	"                                ",
104 	"                                ",
105 	"                                ",
106 	"                                ",
107 	"                                ",
108 	"                                ",
109 	"                                ",
110 	"                                ",
111 	"                                ",
112 	"0,0"
113 };
114 
115 /*****************************************************
116  ****************************************************/
initCursor(const char * image[])117 SDL_Cursor * initCursor(const char * image[])
118 {
119 	int i, row, col, hot_x, hot_y;
120 	Uint8 data[4 * 32];
121 	Uint8 mask[4 * 32];
122 
123 	i = -1;
124 	for (row = 0;row < 32; ++row) {
125 		for (col = 0; col < 32; ++col) {
126 			if (col % 8) {
127 				data[i] <<= 1;
128 				mask[i] <<= 1;
129 			} else {
130 				++i;
131 				data[i] = mask[i] = 0;
132 			}
133 			switch (image[4 + row][col]) {
134 			case 'x':
135 				data[i] |= 0x01;
136 				mask[i] |= 0x01;
137 				break;
138 			case '.':
139 				mask[i] |= 0x01;
140 				break;
141 			case ' ':
142 				break;
143 			}
144 		}
145 	}
146 	sscanf(image[4 + row], "%d,%d", &hot_x, &hot_y);
147 	return SDL_CreateCursor(data, mask, 32, 32, hot_x, hot_y);
148 }
149 
150 
151 /*****************************************************
152  ****************************************************/
getHandCursor()153 SDL_Cursor * getHandCursor()
154 {
155 	if(!handCursor)
156 		handCursor = initCursor(hand);
157 	return handCursor;
158 }
159 
160 /*****************************************************
161  ****************************************************/
getArrowCursor()162 SDL_Cursor * getArrowCursor()
163 {
164 	if(!arrowCursor)
165 		arrowCursor = initCursor(arrow);
166 	return arrowCursor;
167 }
168 
169 
170 /*****************************************************
171  from http://sdldoc.csn.ul.ie/guidevideo.php
172 ****************************************************/
getpixel(SDL_Surface * surface,int x,int y)173 static Uint32 getpixel(SDL_Surface *surface, int x, int y)
174 {
175 	int bpp = surface->format->BytesPerPixel;
176 	/* Here p is the address to the pixel we want to retrieve */
177 	Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
178 
179 	switch(bpp) {
180 	case 1:
181 		return *p;
182 
183 	case 2:
184 		return *(Uint16 *)p;
185 
186 	case 3:
187 		if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
188 			return p[0] << 16 | p[1] << 8 | p[2];
189 		else
190 			return p[0] | p[1] << 8 | p[2] << 16;
191 
192 	case 4:
193 		return *(Uint32 *)p;
194 
195 	default:
196 		return 0;       /* shouldn't happen, but avoids warnings */
197 	}
198 }
199 
200 /*****************************************************
201  ****************************************************/
putpixel(SDL_Surface * surface,int x,int y,Uint32 pixel)202 static void putpixel(SDL_Surface * surface, int x, int y, Uint32 pixel)
203 {
204 	int bpp = surface->format->BytesPerPixel;
205 	/* Here p is the address to the pixel we want to set */
206 	Uint8 * p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
207 
208 	switch(bpp) {
209 	case 1:
210 		*p = pixel;
211 		break;
212 
213 	case 2:
214 		*(Uint16 *)p = pixel;
215 		break;
216 
217 	case 3:
218 		if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
219 			p[0] = (pixel >> 16) & 0xff;
220 			p[1] = (pixel >> 8) & 0xff;
221 			p[2] = pixel & 0xff;
222 		} else {
223 			p[0] = pixel & 0xff;
224 			p[1] = (pixel >> 8) & 0xff;
225 			p[2] = (pixel >> 16) & 0xff;
226 		}
227 		break;
228 
229 	case 4:
230 		*(Uint32 *)p = pixel;
231 		break;
232 	}
233 }
234 
235 /*****************************************************
236  ****************************************************/
surfaceToCursor(SDL_Surface * image,int hx,int hy)237 SDL_Cursor * surfaceToCursor(SDL_Surface *image, int hx, int hy)
238 {
239 	int             w, x, y;
240 	Uint8           *data, *mask, *d, *m, r, g, b;
241 	Uint32          color;
242 
243 	w = (image->w + 7) / 8;
244 	data = (Uint8 *)calloc(w * image->h * 2, 1);
245 	if (data == NULL)
246 		return NULL;
247 
248 	mask = data + w * image->h;
249 	if (SDL_MUSTLOCK(image))
250 		SDL_LockSurface(image);
251 	for (y = 0; y < image->h; y++) {
252 		d = data + y * w;
253 		m = mask + y * w;
254 		for (x = 0; x < image->w; x++) {
255 			color = getpixel(image, x, y);
256 			if ((image->flags & SDL_SRCCOLORKEY) == 0 || color != image->format->colorkey) {
257 				SDL_GetRGB(color, image->format, &r, &g, &b);
258 				color = (r + g + b) / 3;
259 				m[x / 8] |= 128 >> (x & 7);
260 				if (color < 128)
261 					d[x / 8] |= 128 >> (x & 7);
262 			}
263 		}
264 	}
265 	if (SDL_MUSTLOCK(image))
266 		SDL_UnlockSurface(image);
267 
268 	return SDL_CreateCursor(data, mask, w, image->h, hx, hy);
269 }
270