]>
Commit | Line | Data |
---|---|---|
e6d0212c DM |
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 | } |