1 /**
2  * Cursor and app icon mask tests
3 
4  * Copyright (C) 2007  Sylvain Beucler
5 
6  * This file is part of GNU FreeDink
7 
8  * GNU FreeDink is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 3 of the
11  * License, or (at your option) any later version.
12 
13  * GNU FreeDink is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17 
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see
20  * <http://www.gnu.org/licenses/>.
21  */
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <math.h>
26 #include "SDL.h"
27 
28 /* Cursor part based on
29    http://www.libsdl.org/docs/html/sdlcreatecursor.html */
30 
31 static const char *arrow[] = {
32   /* width height num_colors chars_per_pixel */
33   "    32    32        3            1",
34   /* colors */
35   "X c #000000",
36   ". c #ffffff",
37   "  c Transparent",
38   "I c Invereted",
39   /* pixels */
40   "X                               ",
41   "XX                              ",
42   "X.X                             ",
43   "X..X                            ",
44   "X...X                           ",
45   "X.I..X                          ",
46   "X.II..X                         ",
47   "X.III..X                        ",
48   "X.IIII..X                       ",
49   "X.I......X                      ",
50   "X.....XXXXX                     ",
51   "X..X..X                         ",
52   "X.X X..X                        ",
53   "XX  X..X                        ",
54   "X    X..X                       ",
55   "     X..X                       ",
56   "      X..X                      ",
57   "      X..X                      ",
58   "       XX                       ",
59   "                                ",
60   "                                ",
61   "                                ",
62   "                                ",
63   "                                ",
64   "                                ",
65   "                                ",
66   "                                ",
67   "                                ",
68   "                                ",
69   "                                ",
70   "                                ",
71   "                                ",
72   "0,0"
73 };
74 
init_system_cursor(const char * image[])75 static SDL_Cursor *init_system_cursor(const char *image[])
76 {
77   int i, row, col;
78   Uint8 data[4*32];
79   Uint8 mask[4*32];
80   int hot_x, hot_y;
81 
82   i = -1;
83   for ( row=0; row<32; ++row ) {
84     for ( col=0; col<32; ++col ) {
85       if ( col % 8 ) {
86         data[i] <<= 1;
87         mask[i] <<= 1;
88       } else {
89         ++i;
90         data[i] = mask[i] = 0;
91       }
92       switch (image[5+row][col]) {
93         case 'X':
94           data[i] |= 0x01;
95           mask[i] |= 0x01;
96           break;
97         case '.':
98           mask[i] |= 0x01;
99           break;
100         case 'I':
101           data[i] |= 0x01;
102           break;
103         case ' ':
104           break;
105       }
106     }
107   }
108   sscanf(image[5+row], "%d,%d", &hot_x, &hot_y);
109   return SDL_CreateCursor(data, mask, 32, 32, hot_x, hot_y);
110 }
111 
112 
113 /* Create a mask in MSB for using r,g,b as the transparent color */
create_mask_msb(SDL_Surface * source,Uint8 r,Uint8 g,Uint8 b)114 Uint8 *create_mask_msb(SDL_Surface *source, Uint8 r, Uint8 g, Uint8 b) {
115   Uint32 transparent;
116   Uint32 *pixels;
117   SDL_Surface *surface;
118   Uint8 *mask;
119 
120   /* Convert surface to 32bit to ease parsing the pixel data */
121   surface = SDL_CreateRGBSurface(SDL_SWSURFACE, source->w, source->h, 32,
122 			      0xff000000, 0x00ff0000, 0x0000ff00, 0x00000000);
123   if(surface == NULL) {
124     fprintf(stderr, "Could not convert surface to 32bit: %s", SDL_GetError());
125     return NULL;
126   }
127 
128   SDL_BlitSurface(source, NULL, surface, NULL);
129 
130   transparent = SDL_MapRGB(surface->format, r, g, b);
131 
132   if (SDL_MUSTLOCK(surface))
133     SDL_LockSurface(surface);
134   pixels = (Uint32*) surface->pixels;
135   if (SDL_MUSTLOCK(surface))
136     SDL_UnlockSurface(surface);
137 
138   /* 8 bits per Uint8 */
139   mask = malloc(ceil(surface->w / 8.0) * surface->h);
140 
141   {
142     int i, row, col;
143     i = -1;
144     for (row = 0; row < surface->h; row++)
145       {
146 	for (col = 0; col < surface->w; col++)
147 	  {
148 	    /* Shift to the next mask bit */
149 	    if (col % 8 == 0)
150 	      {
151 		i++;
152 		mask[i] = 0;
153 	      }
154 	    else
155 	      {
156 		mask[i] <<= 1;
157 	      }
158 
159 	    /* Set the current mask bit */
160 	    if (pixels[row*surface->w + col] != transparent)
161 	      mask[i] |= 0x01;
162 	  }
163       }
164   }
165   SDL_FreeSurface(surface);
166   return mask;
167 }
168 
169 
main(void)170 int main(void)
171 {
172   SDL_Surface *screen;
173 
174   if (SDL_InitSubSystem(SDL_INIT_VIDEO) == -1)
175     {
176       fprintf(stderr, "SDL_Init: %s\n", SDL_GetError());
177       return 1;
178     }
179 
180   SDL_WM_SetCaption("Cursor test", NULL);
181   SDL_SetCursor(init_system_cursor(arrow));
182 
183   {
184     SDL_Surface *icon;
185     Uint8 *mask;
186 
187     icon = SDL_LoadBMP("../../share/freedink/dink.bmp");
188 
189     mask = create_mask_msb(icon, 255, 255, 0); /* Yellow */
190     if (mask != NULL)
191       {
192 	SDL_WM_SetIcon(icon, mask);
193 	SDL_FreeSurface(icon);
194 	free(mask);
195       }
196   }
197 
198   screen = SDL_SetVideoMode(640, 480, 0, SDL_HWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF);
199   SDL_FillRect(screen, NULL,
200 	       SDL_MapRGB(screen->format, 0, 255, 255));
201   SDL_Flip(screen);
202 
203   {
204     SDL_Event event;
205     int quit = 0;
206     while (SDL_WaitEvent(&event) && !quit)
207       {
208 	switch(event.type)
209 	  {
210 	  case SDL_QUIT:
211 	    quit = 1;
212 	    break;
213 	  case SDL_KEYDOWN:
214 	    if (event.key.keysym.sym == 'q'
215 		|| event.key.keysym.sym == SDLK_ESCAPE)
216 	      quit = 1;
217 	    break;
218 	  }
219       }
220   }
221   return 0;
222 }
223