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