]> Pileus Git - ~andy/gtk/blob - gdk/win32/bdfcursor.c
Change FSF Address
[~andy/gtk] / gdk / win32 / bdfcursor.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 2001 Stefan Ondrejicka
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include "config.h"
19 #include <string.h>
20 #include <stdio.h>
21 #include <errno.h>
22 #include <ctype.h>
23 #include <stdlib.h>
24
25 #include <glib.h>
26
27 typedef struct {
28         gchar   *name;
29         gint    id;
30         gchar   *bitmap;
31         gint    hotx;
32         gint    hoty;
33 } font_info_t;
34
35 typedef struct {
36         gchar   *name;
37         gint    id;
38         gint    width;
39         gint    height;
40         gint    hotx;
41         gint    hoty;
42         gchar   *data;
43 } cursor_info_t;
44
45 static GSList *fonts = NULL;
46 static GSList *cursors = NULL;
47
48 static gint dw,dh;
49
50 static gboolean debug = FALSE;
51
52 #define HEX(c) (((c) >= '0' && (c) <= '9') ? \
53         ((c) - '0') : (toupper(c) - 'A' + 10))
54
55 static void print_font(fi)
56 font_info_t *fi;
57 {
58         int x,y;
59
60         for (y = 0; y < dh; y++)
61         {
62                 for (x = 0; x < dw; x++)
63                 {
64                         printf(fi->bitmap[y*dw+x]? "X" : " ");
65                 }
66                 printf("\n");
67         }
68 }
69
70 static void print_cursor(ci)
71 cursor_info_t *ci;
72 {
73         int x,y;
74
75         for (y = 0; y < ci->height; y++)
76         {
77                 printf("/* ");
78                 for (x = 0; x < ci->width; x++)
79                 {
80                         if (ci->hotx == x && ci->hoty == y)
81                                 printf("o");
82                         else
83                                 switch (ci->data[y*ci->width+x])
84                                 {
85                                         case 0:
86                                                 printf(" ");
87                                         break;
88                                         case 1:
89                                                 printf(".");
90                                         break;
91                                         case 2:
92                                                 printf("X");
93                                         break;
94                                 }
95                 }
96                 printf(" */\n");
97         }
98 }
99
100 static gint read_bdf_font(fname)
101 gchar *fname;
102 {
103         FILE *f;
104         gchar line[2048];
105         gint rv = 0;
106         gboolean startchar = FALSE, startbitmap = FALSE;
107         gchar *charname,*p,*bitmap;
108         gint dx = 0,dy = 0;
109         gint w,h,x,y,py;
110         gint id,tmp;
111
112         dw = 0;
113         dh = 0;
114
115         if (!(f = fopen(fname, "r")))
116         {
117                 perror(fname);
118                 return -1;
119         }
120
121         if (fgets(line, sizeof(line), f) && strncasecmp("STARTFONT ", line, 10))
122         {
123                 printf("!BDF font file\n");
124                 fclose(f);
125                 return -1;
126         }
127         
128         p = line;
129         while (fgets(line, sizeof(line), f))
130         {
131                 if (!startchar)
132                 {
133                         if (!strncasecmp("STARTCHAR ", line, 10))
134                         {
135                                 startchar = TRUE;
136                                 charname = g_strndup(p + 10,
137                                         strcspn(p+10, "\r\n"));
138                         }
139                         else if (!strncasecmp("FONTBOUNDINGBOX ", line, 16))
140                                 sscanf(p+16, "%d %d %d %d", &dw, &dh, &dx, &dy);
141                 }
142                 else
143                 {
144                         if (!strncasecmp("ENDCHAR", line, 7))
145                         {
146                                 font_info_t *nfi;
147
148                                 if (debug)
149                                         printf(" %*s*/\n", dw, "");
150                                 startchar = FALSE;
151                                 startbitmap = FALSE;
152
153                                 nfi = g_malloc(sizeof(font_info_t));
154                                 memset(nfi, '\0', sizeof(font_info_t));
155
156                                 nfi->name = charname;
157                                 nfi->id = id;
158                                 nfi->bitmap = bitmap;
159                                 nfi->hotx = 0 - dx;
160                                 nfi->hoty = 0 - dy;
161
162                                 fonts = g_slist_append(fonts, nfi);
163                         }
164                         else if (startbitmap)
165                         {
166                                 int px,cx;
167                                 guchar mask;
168
169                                 px = x - dx + py * dw;
170                                 for (cx = 0; cx < w; cx++)
171                                 {
172                                         mask = 1 << (3 - (cx % 4));
173
174                                         bitmap[px+cx] =
175                                                 (mask & HEX(line[cx/4])) != 0;
176
177                                         if (debug)
178                                                 printf(bitmap[px+cx] ? "X" : " ");
179                                 }
180                                 py++;
181                                 if (debug)
182                                         printf(" %*s*/\n/* %*s", dw-w, "", dw+dx, "");
183                         }
184                         else if (!strncasecmp("BBX ", line, 4))
185                         {
186                                 sscanf(p+4, "%d %d %d %d", &w, &h, &x, &y);
187                                 if (debug)
188                                         printf("/* %s: */\n/* %*s", charname, dw+dx, "");
189                         }
190                         else if (!strncasecmp("ENCODING ", line, 9))
191                         {
192                                 if (sscanf(p+9, "%d %d", &tmp, &id) != 2)
193                                         id = tmp;
194                         }
195                         else if (!strncasecmp("BITMAP", line, 6))
196                         {
197                                 py = y - dy;
198                                 startbitmap = TRUE;
199                                 bitmap = g_malloc(dw*dh);
200                                 memset(bitmap, '\0', dw*dh);
201                         }
202                 }
203         }
204
205         if (strncasecmp("ENDFONT", line, 7))
206                 rv = -1;
207
208         fclose(f);
209
210         return rv;
211 }
212
213 static gint font_info_compare(fi, name)
214 font_info_t *fi;
215 char *name;
216 {
217         return strcmp(name, fi->name);
218 }
219
220 static cursor_info_t *gen_cursor(bmap, mask)
221 font_info_t *bmap;
222 font_info_t *mask;
223 {
224         cursor_info_t *ci;
225         int bx = dw,by = dh,ex = 0,ey = 0;
226         int i,j;
227
228         for (j = 0; j < dh; j++)
229         {
230                 gboolean havep = FALSE;
231
232                 for (i = 0; i < dw; i++)
233                 {
234                         if (bmap->bitmap[j*dw+i] || mask->bitmap[j*dw+i])
235                         {
236                                 havep = TRUE;
237                                 bx = MIN(bx, i);
238                                 ex = MAX(i+1, ex);
239                         }
240                 }
241
242                 if (havep)
243                 {
244                         by = MIN(by, j);
245                         ey = MAX(ey, j+1);
246                 }
247         }
248
249         ci = g_malloc(sizeof(cursor_info_t));
250         ci->name = g_strdup(bmap->name);
251         ci->id = bmap->id;
252
253         ci->width = ex - bx;
254         ci->height = ey - by;
255
256         ci->hotx = bmap->hotx - bx;
257         ci->hoty = ci->height - (bmap->hoty - by);
258
259         ci->data = g_malloc(ci->width * ci->height);
260         memset(ci->data, '\0', ci->width * ci->height);
261
262         for (j = 0; j < ci->height; j++)
263         {
264                 for (i = 0; i < ci->width; i++)
265                 {
266                         int ofs = (by + j) * dw + bx + i;
267
268                         ci->data[j*ci->width + i] = mask->bitmap[ofs] *
269                                 (1 + bmap->bitmap[ofs]);
270                 }
271         }
272
273         return ci;
274 }
275
276 static void compose_cursors_from_fonts()
277 {
278         GSList *l;
279
280         for (l = g_slist_copy (fonts); l; l = g_slist_delete_link (l,l))
281         {
282                 font_info_t *fi = l->data;
283                 gchar *name;
284                 GSList *ml;
285
286                 name = g_strconcat(fi->name, "_mask", NULL);
287
288                 if ((ml = g_slist_find_custom(fonts, name,
289                         (GCompareFunc) font_info_compare)))
290                 {
291                         cursors = g_slist_append(cursors, gen_cursor(l->data, ml->data));
292                         fonts = g_slist_remove(fonts, l->data);
293                         fonts = g_slist_remove(fonts, ml->data);
294                 }
295
296                 g_free(name);
297         }
298 }
299
300 static char *dump_cursor(ci, id)
301 cursor_info_t *ci;
302 int id;
303 {
304         static gchar cdata[8192];
305         gchar *p;
306         gint i;
307         gint c;
308         gboolean flushed;
309
310         sprintf(cdata, "  { \"%s\", %d, %d, %d, %d, %d, \n    \"",
311                 ci->name, ci->id, ci->width, ci->height, ci->hotx, ci->hoty);
312         p = cdata + strlen(cdata);
313
314         for (i = 0; i < ci->width * ci->height; i++)
315         {
316                 flushed = FALSE;
317
318                 if (!(i%4))
319                         c = 0;
320
321                 c = c << 2;
322
323                 c += ci->data[i];
324
325                 if ((i % 4) == 3)
326                 {
327                         flushed = TRUE;
328                         sprintf(p, "\\%03o", c);
329                         p += strlen(p);
330                 }
331
332                 if (i > 0 && !(i % 64))
333                 {
334                         strcpy(p ,"\"\n    \"");
335                         p += strlen(p);
336                 }
337         }
338         if (!flushed)
339         {
340                 sprintf(p, "\\%03o", c);
341                 p += strlen(p);
342         }
343
344         strcpy(p, "\" }");
345
346         return cdata;
347 }
348
349 static int dump_cursors()
350 {
351         GSList *ptr;
352         FILE *f = stdout;
353
354         fprintf(f, "static const struct { const gchar *name; gint type; guchar width; guchar height; guchar hotx; guchar hoty; guchar *data; } cursors[] = {\n");
355
356         for (ptr = cursors; ptr; ptr = ptr->next)
357         {
358                 if (debug)
359                         print_cursor(ptr->data);
360                 fprintf(f, "%s, \n", dump_cursor(ptr->data));
361         }
362
363         fprintf(f, "  { NULL, 0, 0, 0, 0, 0, NULL },\n};\n");
364
365         return 0;
366 }
367
368 gint main(argc, argv)
369 gint argc;
370 gchar **argv;
371 {
372         if (argc != 2)
373         {
374                 printf("missing parameters !\n");
375                 printf("Usage: %s [BDF cursor file]\n", argv[0]);
376                 return -1;
377         }
378
379         if (g_getenv ("BDFCURSOR_DEBUG") != NULL)
380           debug = TRUE;
381
382         if (read_bdf_font(argv[1]) || !fonts)
383         {
384                 printf("Error reading font\n");
385                 return 1;
386         }
387
388         compose_cursors_from_fonts();
389
390         if (!cursors)
391         {
392                 printf("failed to generate cursors from font!\n");
393                 return 1;
394         }
395
396         dump_cursors();
397
398         if (fonts)
399         {
400                 printf("some fonts remained unconverted!\n");
401                 return 1;
402         }
403
404         return 0;
405 }
406