buildsys: make job safety
[vncterm.git] / genfont.c
1 /*
2  
3      Copyright (C) 2007 Proxmox Server Solutions GmbH
4  
5      Copyright: vzdump is under GNU GPL, the GNU General Public License.
6  
7      This program is free software; you can redistribute it and/or modify
8      it under the terms of the GNU General Public License as published by
9      the Free Software Foundation; version 2 dated June, 1991.
10  
11      This program is distributed in the hope that it will be useful,
12      but WITHOUT ANY WARRANTY; without even the implied warranty of
13      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14      GNU General Public License for more details.
15  
16      You should have received a copy of the GNU General Public License
17      along with this program; if not, write to the Free Software
18      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19      02111-1307, USA.
20  
21      Author: Dietmar Maurer <dietmar@proxmox.com>
22
23 */
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <zlib.h> /* read compressed console fonts */
28 #include <glob.h>
29 #include <string.h>
30
31 /* map unicode to font */
32 static unsigned short vt_fontmap[65536];
33
34 /* font glyph storage */
35 static unsigned char *vt_font_data = NULL;
36 static int vt_font_size = 0;
37 static int vt_font_maxsize = 0;
38
39 /* PSF stuff */
40
41
42 #define PSF_MAGIC1      0x36
43 #define PSF_MAGIC2      0x04
44
45 #define PSF_MODE256NOSFM        0
46 #define PSF_MODE512NOSFM        1
47 #define PSF_MODE256SFM          2
48 #define PSF_MODE512SFM          3
49
50 #define PSF_SEPARATOR   0xFFFF
51
52 struct psf_header
53 {
54   unsigned char magic1, magic2; /* Magic number */
55   unsigned char mode;           /* PSF font mode */
56   unsigned char charheight;     /* Character size */
57 };
58
59 #define PSF_MAGIC_OK(x) ((x).magic1 == PSF_MAGIC1 && (x).magic2 == PSF_MAGIC2)
60 #define PSF_MODE_VALID(x) ((x) <= PSF_MODE512SFM)
61 #define PSF_MODE_HAS512(x) (((x) == 1) || ((x) == 3))
62 #define PSF_MODE_HASSFM(x) (((x) == 2) || ((x) == 3))
63
64 typedef unsigned short unicode;
65
66 static int
67 font_add_glyph (const char *data)
68 {
69
70   if (vt_font_size >= vt_font_maxsize) {
71     vt_font_maxsize += 256;
72     vt_font_data = realloc (vt_font_data, vt_font_maxsize*16);
73   }
74
75   memcpy (vt_font_data + vt_font_size*16, data, 16);
76
77   vt_font_size += 1;
78   
79   return vt_font_size - 1;
80 }
81
82 static int
83 load_psf_font (const char *filename, int is_default)
84 {
85   struct psf_header psfhdr;
86  
87   gzFile *f = gzopen (filename, "rb");
88   if (f == NULL) {
89           fprintf (stderr, "unable to read file %s\n", filename);
90           exit(-1);
91   }
92
93   // read psf header
94   if (gzread(f, &psfhdr, sizeof(struct psf_header)) !=  sizeof(struct psf_header)) {
95     fprintf (stderr, "unable to read psf font header (%s)\n", filename);
96     gzclose (f);
97     return -1;
98   }
99
100   if (!PSF_MAGIC_OK(psfhdr) || !PSF_MODE_VALID(psfhdr.mode) || 
101       !PSF_MODE_HASSFM(psfhdr.mode) || (psfhdr.charheight != 16)) {
102     fprintf (stderr, "no valid 8*16 psf font (%s)\n", filename);
103     gzclose (f);
104     return -1;
105   }
106
107   int charcount = ((PSF_MODE_HAS512(psfhdr.mode)) ? 512 : 256);
108
109   int size = 16*charcount;
110
111   char *chardata = (char *)malloc (size);
112
113   if (size != gzread(f, chardata, size)) {
114     fprintf (stderr, "unable to read font character data (%s)\n", filename);
115     gzclose (f);
116     return -1;
117   }
118
119   unicode unichar;
120   int glyph;
121
122   for (glyph = 0 ;glyph < charcount ;glyph++) {
123     int fi = 0;
124     while (gzread (f, &unichar, sizeof(unicode)) ==  sizeof(unicode) && 
125            (unichar != PSF_SEPARATOR)) {
126       if (!vt_fontmap[unichar]) {
127         if (!fi) {
128           fi = font_add_glyph (chardata + glyph*16);
129         }
130         vt_fontmap[unichar] = fi;
131       }
132     }
133
134     if (is_default && fi && glyph < 256) {
135       vt_fontmap[0xf000 + glyph] = fi;      
136     }
137   }
138
139   free (chardata);
140   gzclose (f);
141
142   return 0;
143 }
144
145 void
146 print_glyphs ()
147 {
148   int i, j;
149
150   printf ("static int vt_font_size = %d;\n\n", vt_font_size);
151
152   printf ("static unsigned char vt_font_data[] = {\n");
153   for (i = 0; i < vt_font_size; i++) {
154     printf ("\t/* %d 0x%02x */\n", i, i);
155     for (j = 0; j < 16; j++) {
156       unsigned char d = vt_font_data[i*16+j];
157       printf ("\t0x%02X, /* ", d);
158       int k;
159       for (k = 128; k > 0; k = k>>1) {
160         printf ("%c", (d & k) ? '1': '0'); 
161       }  
162       printf (" */\n");
163     }
164     printf ("\n");
165   }
166   printf ("};\n\n");
167
168   printf ("static unsigned short vt_fontmap[65536] = {\n");
169   for (i = 0; i < 0x0ffff; i++) {
170     printf ("\t/* 0x%04X => */ %d,\n", i, vt_fontmap[i]);
171   }
172   printf ("};\n\n");
173
174 }
175
176 int 
177 main (int argc, char** argv)
178 {
179   char empty[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
180   glob_t globbuf;
181
182   font_add_glyph (empty);
183
184   /* font load order is only important if glyphs are redefined */
185   load_psf_font ("/usr/share/consolefonts/default8x16.psf.gz", 1);  /* vga default */
186   load_psf_font ("/usr/share/consolefonts/lat1u-16.psf.gz", 0);     /* Latin-1 */
187   load_psf_font ("/usr/share/consolefonts/lat2u-16.psf.gz", 0);     /* Latin-2 */
188   load_psf_font ("/usr/share/consolefonts/lat4u-16.psf.gz", 0);     /* Baltic */
189
190   load_psf_font ("/usr/share/consolefonts/iso07.f16.psf.gz", 0);    /* Greek */
191   load_psf_font ("/usr/share/consolefonts/Goha-16.psf.gz", 0);      /* Ethiopic */
192
193   /* fixme: Arabic, Japanese letters ? */
194
195   if (0) {
196     glob("/usr/share/consolefonts/*", GLOB_ERR, NULL, &globbuf);
197
198     int i;
199     for (i = 0; i < globbuf.gl_pathc; i++) {
200       int pc = vt_font_size;
201       load_psf_font (globbuf.gl_pathv[i], 0);
202       if (vt_font_size > pc) {
203         printf ("TEST: %s %d\n", globbuf.gl_pathv[i], vt_font_size - pc);
204       }
205     }
206   } else {
207
208     print_glyphs ();
209
210   }
211
212   exit (0);
213 }