2 * kmscon - Generate Unifont data files
4 * Copyright (c) 2012 Ted Kotz <ted@kotz.us>
5 * Copyright (c) 2012-2013 David Herrmann <dh.herrmann@googlemail.com>
7 * Permission is hereby granted, free of charge, to any person obtaining
8 * a copy of this software and associated documentation files
9 * (the "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sublicense, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 * This converts the hex-encoded Unifont data into a C-array that is used by the
30 * unifont-font-renderer.
39 #define MAX_DATA_SIZE 512
41 struct unifont_glyph {
42 struct unifont_glyph *next;
45 char data[MAX_DATA_SIZE];
48 static uint8_t hex_val(char c)
50 if (c >= '0' && c <= '9')
52 else if (c >= 'a' && c <= 'f')
54 else if (c >= 'A' && c <= 'F')
57 fprintf(stderr, "genunifont: invalid hex-code %c\n", c);
61 static void print_unifont_glyph(FILE *out, const struct unifont_glyph *g)
71 fprintf(stderr, "genunifont: invalid data size %d for %x",
72 g->len, g->codepoint);
76 fprintf(out, "%c", g->len / 2);
77 for (i = 0; i < g->len; i += 2) {
78 val = hex_val(g->data[i]) << 4;
79 val |= hex_val(g->data[i + 1]);
80 fprintf(out, "%c", val);
82 for ( ; i < 64; i += 2)
83 fprintf(out, "%c", 0);
86 static int build_unifont_glyph(struct unifont_glyph *g, const char *buf)
89 const char *orig = buf;
92 while (*buf && *buf != ':') {
94 val += hex_val(*buf++);
98 fprintf(stderr, "genunifont: invalid file format: %s\n", orig);
104 while (*buf && *buf != '\n' && g->len < MAX_DATA_SIZE) {
105 g->data[g->len] = *buf++;
112 static int parse_single_file(FILE *out, FILE *in)
114 static const struct unifont_glyph replacement = {
117 .data = "0000007E665A5A7A76767E76767E0000"
119 char buf[MAX_DATA_SIZE];
120 struct unifont_glyph *g, **iter, *list, *last;
122 unsigned long status_max, status_cur;
123 unsigned long perc_prev, perc_now;
125 if (fseek(in, 0, SEEK_END) != 0) {
126 fprintf(stderr, "genunifont: cannot seek: %m\n");
130 status_max = ftell(in);
131 if (status_max < 0) {
132 fprintf(stderr, "genunifont: cannot ftell: %m\n");
136 if (status_max < 1) {
137 fprintf(stderr, "genunifont: empty file\n");
148 fprintf(stderr, "Finished: %3ld%%", perc_now);
150 while (fgets(buf, sizeof(buf) - 1, in) != NULL) {
151 /* print status update in percent */
152 perc_now = status_cur * 100 / status_max;
153 if (perc_now > perc_prev) {
154 perc_prev = perc_now;
155 fprintf(stderr, "\b\b\b\b%3ld%%", perc_now);
158 status_cur += strlen(buf);
160 /* ignore comments */
164 /* allocate new glyph */
165 g = malloc(sizeof(*g));
167 fprintf(stderr, "genunifont: out of memory\n");
170 memset(g, 0, sizeof(*g));
172 /* read glyph data */
173 ret = build_unifont_glyph(g, buf);
179 /* find glyph position */
180 if (last && last->codepoint < g->codepoint) {
184 while (*iter && (*iter)->codepoint < g->codepoint)
185 iter = &(*iter)->next;
187 if (*iter && (*iter)->codepoint == g->codepoint) {
188 fprintf(stderr, "glyph %d used twice\n",
195 /* insert glyph into single-linked list */
202 fprintf(stderr, "\b\b\b\b%3d%%\n", 100);
204 /* print all glyph-data to output file */
210 /* print replacements if glyphs are missing */
211 while (num++ < g->codepoint)
212 print_unifont_glyph(out, &replacement);
214 print_unifont_glyph(out, g);
221 int main(int argc, char **argv)
227 fprintf(stderr, "genunifont: use ./genunifont <outputfile> <inputfiles>\n");
232 out = fopen(argv[1], "wb");
234 fprintf(stderr, "genunifont: cannot open output %s: %m\n",
240 fprintf(stderr, "genunifont: parsing input %s\n", argv[2]);
241 in = fopen(argv[2], "rb");
243 fprintf(stderr, "genunifont: cannot open %s: %m\n",
247 ret = parse_single_file(out, in);
249 fprintf(stderr, "genunifont: parsing input %s failed",