2 * Copyright (c) 2009 The FreeBSD Foundation
5 * This software was developed by Ed Schouten under sponsorship from the
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
33 #include <sys/endian.h>
34 #include <sys/param.h>
35 #include <sys/queue.h>
43 static unsigned int width, wbytes, height;
46 TAILQ_ENTRY(glyph) g_list;
51 static TAILQ_HEAD(, glyph) glyph_list = TAILQ_HEAD_INITIALIZER(glyph_list);
52 static unsigned int glyph_total, glyph_normal, glyph_bold,
53 glyph_unique, glyph_dupe;
56 TAILQ_ENTRY(mapping) m_list;
58 unsigned int m_length;
59 struct glyph *m_glyph;
62 TAILQ_HEAD(mapping_list, mapping);
63 static struct mapping_list mapping_list_normal =
64 TAILQ_HEAD_INITIALIZER(mapping_list_normal);
65 static struct mapping_list mapping_list_bold =
66 TAILQ_HEAD_INITIALIZER(mapping_list_bold);
67 static unsigned int mapping_total, mapping_normal, mapping_normal_folded,
68 mapping_bold, mapping_bold_folded, mapping_unique, mapping_dupe;
75 "usage: fontcvt width height normal.bdf bold.bdf out.fnt\n");
80 add_mapping(struct glyph *gl, unsigned int c, int bold)
83 struct mapping_list *ml;
90 TAILQ_FOREACH(mp, &mapping_list_normal, m_list) {
93 else if (mp->m_char > c)
98 * No mapping is needed if it's equal to the
101 if (mp->m_glyph == gl) {
109 "Character %u not in normal font!\n", c);
114 mp = malloc(sizeof *mp);
119 ml = bold ? &mapping_list_bold : &mapping_list_normal;
120 if (TAILQ_LAST(ml, mapping_list) != NULL &&
121 TAILQ_LAST(ml, mapping_list)->m_char >= c) {
122 fprintf(stderr, "Bad ordering at character %u\n", c);
125 TAILQ_INSERT_TAIL(ml, mp, m_list);
136 static struct glyph *
137 add_glyph(const uint8_t *bytes, int bold, int fallback)
147 TAILQ_FOREACH(gl, &glyph_list, g_list) {
148 if (memcmp(gl->g_data, bytes, wbytes * height) == 0) {
154 gl = malloc(sizeof *gl);
155 gl->g_data = malloc(wbytes * height);
156 memcpy(gl->g_data, bytes, wbytes * height);
158 TAILQ_INSERT_HEAD(&glyph_list, gl, g_list);
160 TAILQ_INSERT_TAIL(&glyph_list, gl, g_list);
167 parse_bdf(const char *filename, int bold __unused)
172 uint8_t bytes[wbytes * height];
173 unsigned int curchar = 0, i, line;
176 fp = fopen(filename, "r");
182 while ((ln = fgetln(fp, &length)) != NULL) {
183 ln[length - 1] = '\0';
185 if (strncmp(ln, "ENCODING ", 9) == 0) {
186 curchar = atoi(ln + 9);
189 if (strcmp(ln, "BITMAP") == 0) {
190 for (i = 0; i < height; i++) {
191 if ((ln = fgetln(fp, &length)) == NULL) {
192 fprintf(stderr, "Unexpected EOF!\n");
195 ln[length - 1] = '\0';
196 sscanf(ln, "%x", &line);
199 } else if (wbytes == 2) {
200 bytes[i * 2 + 0] = line >> 8;
201 bytes[i * 2 + 1] = line;
204 "Unsupported wbytes!\n");
209 /* Prevent adding two glyphs for 0xFFFD */
210 if (curchar == 0xFFFD) {
212 gl = add_glyph(bytes, bold, 1);
213 } else if (curchar >= 0x20) {
214 gl = add_glyph(bytes, bold, 0);
215 if (add_mapping(gl, curchar, bold) != 0)
228 unsigned int idx = 0;
230 TAILQ_FOREACH(gl, &glyph_list, g_list)
235 write_glyphs(FILE *fp)
239 TAILQ_FOREACH(gl, &glyph_list, g_list)
240 fwrite(gl->g_data, wbytes * height, 1, fp);
244 fold_mappings(int bold)
246 struct mapping_list *ml;
247 struct mapping *mn, *mp, *mbase;
250 ml = &mapping_list_bold;
252 ml = &mapping_list_normal;
254 mp = mbase = TAILQ_FIRST(ml);
255 for (mp = mbase = TAILQ_FIRST(ml); mp != NULL; mp = mn) {
256 mn = TAILQ_NEXT(mp, m_list);
257 if (mn != NULL && mn->m_char == mp->m_char + 1 &&
258 mn->m_glyph->g_index == mp->m_glyph->g_index + 1)
260 mbase->m_length = mp->m_char - mbase->m_char + 1;
263 mapping_bold_folded++;
265 mapping_normal_folded++;
269 struct file_mapping {
271 uint16_t destination;
276 write_mappings(FILE *fp, int bold)
278 struct mapping_list *ml;
280 struct file_mapping fm;
281 unsigned int i = 0, j = 0;
284 ml = &mapping_list_bold;
286 ml = &mapping_list_normal;
288 TAILQ_FOREACH(mp, ml, m_list) {
290 if (mp->m_length > 0) {
292 fm.source = htobe32(mp->m_char);
293 fm.destination = htobe16(mp->m_glyph->g_index);
294 fm.length = htobe16(mp->m_length - 1);
295 fwrite(&fm, sizeof fm, 1, fp);
306 uint16_t nmappings_normal;
307 uint16_t nmappings_bold;
311 write_fnt(const char *filename)
314 struct file_header fh = {
318 fp = fopen(filename, "wb");
326 fh.nglyphs = htobe16(glyph_unique);
327 fh.nmappings_normal = htobe16(mapping_normal_folded);
328 fh.nmappings_bold = htobe16(mapping_bold_folded);
329 fwrite(&fh, sizeof fh, 1, fp);
332 write_mappings(fp, 0);
333 write_mappings(fp, 1);
339 main(int argc, char *argv[])
342 assert(sizeof(struct file_header) == 16);
343 assert(sizeof(struct file_mapping) == 8);
348 width = atoi(argv[1]);
349 wbytes = howmany(width, 8);
350 height = atoi(argv[2]);
352 if (parse_bdf(argv[3], 0) != 0)
354 if (parse_bdf(argv[4], 1) != 0)
359 if (write_fnt(argv[5]) != 0)
364 "- glyph_total: %5u\n"
365 "- glyph_normal: %5u\n"
366 "- glyph_bold: %5u\n"
367 "- glyph_unique: %5u\n"
368 "- glyph_dupe: %5u\n"
369 "- mapping_total: %5u\n"
370 "- mapping_normal: %5u\n"
371 "- mapping_normal_folded: %5u\n"
372 "- mapping_bold: %5u\n"
373 "- mapping_bold_folded: %5u\n"
374 "- mapping_unique: %5u\n"
375 "- mapping_dupe: %5u\n",
377 glyph_normal, glyph_bold,
378 glyph_unique, glyph_dupe,
380 mapping_normal, mapping_normal_folded,
381 mapping_bold, mapping_bold_folded,
382 mapping_unique, mapping_dupe);