vtfontcvt.c revision 267298
1219888Sed/*- 2267123Semaste * Copyright (c) 2009, 2014 The FreeBSD Foundation 3219888Sed * All rights reserved. 4219888Sed * 5219888Sed * This software was developed by Ed Schouten under sponsorship from the 6219888Sed * FreeBSD Foundation. 7219888Sed * 8219888Sed * Redistribution and use in source and binary forms, with or without 9219888Sed * modification, are permitted provided that the following conditions 10219888Sed * are met: 11219888Sed * 1. Redistributions of source code must retain the above copyright 12219888Sed * notice, this list of conditions and the following disclaimer. 13219888Sed * 2. Redistributions in binary form must reproduce the above copyright 14219888Sed * notice, this list of conditions and the following disclaimer in the 15219888Sed * documentation and/or other materials provided with the distribution. 16219888Sed * 17219888Sed * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18219888Sed * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19219888Sed * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20219888Sed * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21219888Sed * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22219888Sed * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23219888Sed * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24219888Sed * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25219888Sed * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26219888Sed * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27219888Sed * SUCH DAMAGE. 28219888Sed */ 29219888Sed 30219888Sed#include <sys/cdefs.h> 31219888Sed__FBSDID("$FreeBSD: head/tools/tools/vt/fontcvt/fontcvt.c 267298 2014-06-09 20:49:13Z emaste $"); 32219888Sed 33267035Semaste#include <sys/types.h> 34267035Semaste#include <sys/fnv_hash.h> 35219888Sed#include <sys/endian.h> 36219888Sed#include <sys/param.h> 37219888Sed#include <sys/queue.h> 38219888Sed 39219888Sed#include <assert.h> 40219888Sed#include <stdint.h> 41219888Sed#include <stdio.h> 42219888Sed#include <stdlib.h> 43219888Sed#include <string.h> 44267011Semaste#include <unistd.h> 45219888Sed 46259680Semaste#define VFNT_MAPS 4 47259680Semaste#define VFNT_MAP_NORMAL 0 48259680Semaste#define VFNT_MAP_BOLD 2 49259680Semaste 50267011Semastestatic unsigned int width = 8, wbytes, height = 16; 51219888Sed 52219888Sedstruct glyph { 53219888Sed TAILQ_ENTRY(glyph) g_list; 54267035Semaste SLIST_ENTRY(glyph) g_hash; 55219888Sed uint8_t *g_data; 56219888Sed unsigned int g_index; 57219888Sed}; 58219888Sed 59267035Semaste#define FONTCVT_NHASH 4096 60259680SemasteTAILQ_HEAD(glyph_list, glyph); 61267035Semastestatic SLIST_HEAD(, glyph) glyph_hash[FONTCVT_NHASH]; 62259680Semastestatic struct glyph_list glyphs[VFNT_MAPS] = { 63259680Semaste TAILQ_HEAD_INITIALIZER(glyphs[0]), 64259680Semaste TAILQ_HEAD_INITIALIZER(glyphs[1]), 65259680Semaste TAILQ_HEAD_INITIALIZER(glyphs[2]), 66259680Semaste TAILQ_HEAD_INITIALIZER(glyphs[3]), 67259680Semaste}; 68259680Semastestatic unsigned int glyph_total, glyph_count[4], glyph_unique, glyph_dupe; 69219888Sed 70219888Sedstruct mapping { 71219888Sed TAILQ_ENTRY(mapping) m_list; 72219888Sed unsigned int m_char; 73219888Sed unsigned int m_length; 74219888Sed struct glyph *m_glyph; 75219888Sed}; 76219888Sed 77219888SedTAILQ_HEAD(mapping_list, mapping); 78259680Semastestatic struct mapping_list maps[VFNT_MAPS] = { 79259680Semaste TAILQ_HEAD_INITIALIZER(maps[0]), 80259680Semaste TAILQ_HEAD_INITIALIZER(maps[1]), 81259680Semaste TAILQ_HEAD_INITIALIZER(maps[2]), 82259680Semaste TAILQ_HEAD_INITIALIZER(maps[3]), 83259680Semaste}; 84259680Semastestatic unsigned int mapping_total, map_count[4], map_folded_count[4], 85259680Semaste mapping_unique, mapping_dupe; 86219888Sed 87219888Sedstatic void 88219888Sedusage(void) 89219888Sed{ 90219888Sed 91267298Semaste errx(1, 92267298Semaste"usage: fontcvt [-w width] [-h height] [-v] normal.bdf [bold.bdf] out.fnt\n"); 93219888Sed exit(1); 94219888Sed} 95219888Sed 96219888Sedstatic int 97259680Semasteadd_mapping(struct glyph *gl, unsigned int c, unsigned int map_idx) 98219888Sed{ 99219888Sed struct mapping *mp; 100219888Sed struct mapping_list *ml; 101219888Sed 102219888Sed mapping_total++; 103219888Sed 104259680Semaste if (map_idx >= VFNT_MAP_BOLD) { 105219888Sed int found = 0; 106259680Semaste unsigned normal_map_idx = map_idx - VFNT_MAP_BOLD; 107219888Sed 108259680Semaste TAILQ_FOREACH(mp, &maps[normal_map_idx], m_list) { 109219888Sed if (mp->m_char < c) 110219888Sed continue; 111219888Sed else if (mp->m_char > c) 112219888Sed break; 113219888Sed found = 1; 114219888Sed 115219888Sed /* 116219888Sed * No mapping is needed if it's equal to the 117219888Sed * normal mapping. 118219888Sed */ 119219888Sed if (mp->m_glyph == gl) { 120219888Sed mapping_dupe++; 121219888Sed return (0); 122219888Sed } 123219888Sed } 124219888Sed 125219888Sed if (!found) { 126219888Sed fprintf(stderr, 127219888Sed "Character %u not in normal font!\n", c); 128219888Sed return (1); 129219888Sed } 130219888Sed } 131219888Sed 132219888Sed mp = malloc(sizeof *mp); 133219888Sed mp->m_char = c; 134219888Sed mp->m_glyph = gl; 135219888Sed mp->m_length = 0; 136219888Sed 137259680Semaste ml = &maps[map_idx]; 138219888Sed if (TAILQ_LAST(ml, mapping_list) != NULL && 139219888Sed TAILQ_LAST(ml, mapping_list)->m_char >= c) { 140267298Semaste errx(1, "Bad ordering at character %u\n", c); 141219888Sed return (1); 142219888Sed } 143219888Sed TAILQ_INSERT_TAIL(ml, mp, m_list); 144219888Sed 145259680Semaste map_count[map_idx]++; 146219888Sed mapping_unique++; 147219888Sed 148219888Sed return (0); 149219888Sed} 150219888Sed 151219888Sedstatic struct glyph * 152259680Semasteadd_glyph(const uint8_t *bytes, unsigned int map_idx, int fallback) 153219888Sed{ 154219888Sed struct glyph *gl; 155267035Semaste int hash; 156219888Sed 157219888Sed glyph_total++; 158259680Semaste glyph_count[map_idx]++; 159219888Sed 160267035Semaste hash = fnv_32_buf(bytes, wbytes * height, FNV1_32_INIT) % FONTCVT_NHASH; 161267035Semaste SLIST_FOREACH(gl, &glyph_hash[hash], g_hash) { 162267035Semaste if (memcmp(gl->g_data, bytes, wbytes * height) == 0) { 163267035Semaste glyph_dupe++; 164267035Semaste return (gl); 165219888Sed } 166219888Sed } 167219888Sed 168219888Sed gl = malloc(sizeof *gl); 169219888Sed gl->g_data = malloc(wbytes * height); 170219888Sed memcpy(gl->g_data, bytes, wbytes * height); 171219888Sed if (fallback) 172259680Semaste TAILQ_INSERT_HEAD(&glyphs[map_idx], gl, g_list); 173219888Sed else 174259680Semaste TAILQ_INSERT_TAIL(&glyphs[map_idx], gl, g_list); 175267035Semaste SLIST_INSERT_HEAD(&glyph_hash[hash], gl, g_hash); 176219888Sed 177219888Sed glyph_unique++; 178219888Sed return (gl); 179219888Sed} 180219888Sed 181219888Sedstatic int 182267123Semasteadd_char(unsigned curchar, unsigned map_idx, uint8_t *bytes, uint8_t *bytes_r) 183267123Semaste{ 184267123Semaste struct glyph *gl; 185267123Semaste 186267123Semaste /* Prevent adding two glyphs for 0xFFFD */ 187267123Semaste if (curchar == 0xFFFD) { 188267123Semaste if (map_idx < VFNT_MAP_BOLD) 189267123Semaste gl = add_glyph(bytes, 0, 1); 190267123Semaste } else if (curchar >= 0x20) { 191267123Semaste gl = add_glyph(bytes, map_idx, 0); 192267123Semaste if (add_mapping(gl, curchar, map_idx) != 0) 193267123Semaste return (1); 194267123Semaste if (bytes_r != NULL) { 195267123Semaste gl = add_glyph(bytes_r, map_idx + 1, 0); 196267123Semaste if (add_mapping(gl, curchar, 197267123Semaste map_idx + 1) != 0) 198267123Semaste return (1); 199267123Semaste } 200267123Semaste } 201267123Semaste return (0); 202267123Semaste} 203267123Semaste 204267123Semaste 205267123Semastestatic int 206259680Semasteparse_bitmap_line(uint8_t *left, uint8_t *right, unsigned int line, 207259680Semaste unsigned int dwidth) 208219888Sed{ 209259680Semaste uint8_t *p; 210259680Semaste unsigned int i, subline; 211259680Semaste 212259680Semaste if (dwidth != width && dwidth != width * 2) { 213267298Semaste errx(1, 214267298Semaste "Bitmap with unsupported width %u!\n", dwidth); 215259680Semaste return (1); 216259680Semaste } 217259680Semaste 218259680Semaste /* Move pixel data right to simplify splitting double characters. */ 219259680Semaste line >>= (howmany(dwidth, 8) * 8) - dwidth; 220259680Semaste 221259680Semaste for (i = dwidth / width; i > 0; i--) { 222259680Semaste p = (i == 2) ? right : left; 223259680Semaste 224259680Semaste subline = line & ((1 << width) - 1); 225259680Semaste subline <<= (howmany(width, 8) * 8) - width; 226259680Semaste 227259680Semaste if (wbytes == 1) { 228259680Semaste *p = subline; 229259680Semaste } else if (wbytes == 2) { 230259680Semaste *p++ = subline >> 8; 231259680Semaste *p = subline; 232259680Semaste } else { 233267298Semaste errx(1, 234259680Semaste "Unsupported wbytes %u!\n", wbytes); 235259680Semaste return (1); 236259680Semaste } 237259680Semaste 238259680Semaste line >>= width; 239259680Semaste } 240259680Semaste 241259680Semaste return (0); 242259680Semaste} 243259680Semaste 244259680Semastestatic int 245267123Semasteparse_bdf(FILE *fp, unsigned int map_idx) 246259680Semaste{ 247219888Sed char *ln; 248219888Sed size_t length; 249259680Semaste uint8_t bytes[wbytes * height], bytes_r[wbytes * height]; 250259680Semaste unsigned int curchar = 0, dwidth = 0, i, line; 251219888Sed 252219888Sed while ((ln = fgetln(fp, &length)) != NULL) { 253219888Sed ln[length - 1] = '\0'; 254219888Sed 255219888Sed if (strncmp(ln, "ENCODING ", 9) == 0) { 256219888Sed curchar = atoi(ln + 9); 257219888Sed } 258219888Sed 259259680Semaste if (strncmp(ln, "DWIDTH ", 7) == 0) { 260259680Semaste dwidth = atoi(ln + 7); 261259680Semaste } 262259680Semaste 263267126Semaste if (strncmp(ln, "BITMAP", 6) == 0 && 264267126Semaste (ln[6] == ' ' || ln[6] == '\0')) { 265219888Sed for (i = 0; i < height; i++) { 266219888Sed if ((ln = fgetln(fp, &length)) == NULL) { 267267298Semaste errx(1, "Unexpected EOF!\n"); 268219888Sed return (1); 269219888Sed } 270219888Sed ln[length - 1] = '\0'; 271219888Sed sscanf(ln, "%x", &line); 272259680Semaste if (parse_bitmap_line(bytes + i * wbytes, 273259680Semaste bytes_r + i * wbytes, line, dwidth) != 0) 274219888Sed return (1); 275219888Sed } 276219888Sed 277267123Semaste if (add_char(curchar, map_idx, bytes, 278267123Semaste dwidth == width * 2 ? bytes_r : NULL) != 0) 279267123Semaste return (1); 280267123Semaste } 281267123Semaste } 282267123Semaste 283267123Semaste return (0); 284267123Semaste} 285267123Semaste 286267123Semastestatic int 287267123Semasteparse_hex(FILE *fp, unsigned int map_idx) 288267123Semaste{ 289267123Semaste char *ln, *p; 290267123Semaste char fmt_str[8]; 291267123Semaste size_t length; 292267123Semaste uint8_t bytes[wbytes * height], bytes_r[wbytes * height]; 293267123Semaste unsigned curchar = 0, i, line, chars_per_row, dwidth; 294267123Semaste 295267123Semaste while ((ln = fgetln(fp, &length)) != NULL) { 296267123Semaste ln[length - 1] = '\0'; 297267123Semaste 298267123Semaste if (strncmp(ln, "# Height: ", 10) == 0) { 299267123Semaste height = atoi(ln + 10); 300267123Semaste } else if (strncmp(ln, "# Width: ", 9) == 0) { 301267123Semaste width = atoi(ln + 9); 302267123Semaste } else if (sscanf(ln, "%4x:", &curchar)) { 303267123Semaste p = ln + 5; 304267123Semaste chars_per_row = strlen(p) / height; 305267123Semaste dwidth = width; 306267123Semaste if (chars_per_row / 2 > width / 8) 307267123Semaste dwidth *= 2; /* Double-width character. */ 308267123Semaste snprintf(fmt_str, sizeof(fmt_str), "%%%ux", 309267123Semaste chars_per_row); 310267123Semaste 311267123Semaste for (i = 0; i < height; i++) { 312267123Semaste sscanf(p, fmt_str, &line); 313267123Semaste p += chars_per_row; 314267123Semaste if (parse_bitmap_line(bytes + i * wbytes, 315267123Semaste bytes_r + i * wbytes, line, dwidth) != 0) 316219888Sed return (1); 317219888Sed } 318267123Semaste 319267123Semaste if (add_char(curchar, map_idx, bytes, 320267123Semaste dwidth == width * 2 ? bytes_r : NULL) != 0) 321267123Semaste return (1); 322219888Sed } 323219888Sed } 324219888Sed return (0); 325219888Sed} 326219888Sed 327267123Semastestatic int 328267123Semasteparse_file(const char *filename, unsigned int map_idx) 329267123Semaste{ 330267123Semaste FILE *fp; 331267123Semaste size_t len; 332267123Semaste 333267123Semaste fp = fopen(filename, "r"); 334267123Semaste if (fp == NULL) { 335267123Semaste perror(filename); 336267123Semaste return (1); 337267123Semaste } 338267123Semaste len = strlen(filename); 339267123Semaste if (len > 4 && strcasecmp(filename + len - 4, ".hex") == 0) 340267123Semaste return parse_hex(fp, map_idx); 341267123Semaste return parse_bdf(fp, map_idx); 342267123Semaste} 343267123Semaste 344219888Sedstatic void 345219888Sednumber_glyphs(void) 346219888Sed{ 347219888Sed struct glyph *gl; 348259680Semaste unsigned int i, idx = 0; 349219888Sed 350259680Semaste for (i = 0; i < VFNT_MAPS; i++) 351259680Semaste TAILQ_FOREACH(gl, &glyphs[i], g_list) 352259680Semaste gl->g_index = idx++; 353219888Sed} 354219888Sed 355219888Sedstatic void 356219888Sedwrite_glyphs(FILE *fp) 357219888Sed{ 358219888Sed struct glyph *gl; 359259680Semaste unsigned int i; 360219888Sed 361259680Semaste for (i = 0; i < VFNT_MAPS; i++) { 362259680Semaste TAILQ_FOREACH(gl, &glyphs[i], g_list) 363259680Semaste fwrite(gl->g_data, wbytes * height, 1, fp); 364259680Semaste } 365219888Sed} 366219888Sed 367219888Sedstatic void 368259680Semastefold_mappings(unsigned int map_idx) 369219888Sed{ 370259680Semaste struct mapping_list *ml = &maps[map_idx]; 371219888Sed struct mapping *mn, *mp, *mbase; 372219888Sed 373219888Sed mp = mbase = TAILQ_FIRST(ml); 374219888Sed for (mp = mbase = TAILQ_FIRST(ml); mp != NULL; mp = mn) { 375219888Sed mn = TAILQ_NEXT(mp, m_list); 376219888Sed if (mn != NULL && mn->m_char == mp->m_char + 1 && 377219888Sed mn->m_glyph->g_index == mp->m_glyph->g_index + 1) 378219888Sed continue; 379219888Sed mbase->m_length = mp->m_char - mbase->m_char + 1; 380219888Sed mbase = mp = mn; 381259680Semaste map_folded_count[map_idx]++; 382219888Sed } 383219888Sed} 384219888Sed 385219888Sedstruct file_mapping { 386219888Sed uint32_t source; 387219888Sed uint16_t destination; 388219888Sed uint16_t length; 389219888Sed} __packed; 390219888Sed 391219888Sedstatic void 392259680Semastewrite_mappings(FILE *fp, unsigned int map_idx) 393219888Sed{ 394259680Semaste struct mapping_list *ml = &maps[map_idx]; 395219888Sed struct mapping *mp; 396219888Sed struct file_mapping fm; 397219888Sed unsigned int i = 0, j = 0; 398219888Sed 399219888Sed TAILQ_FOREACH(mp, ml, m_list) { 400219888Sed j++; 401219888Sed if (mp->m_length > 0) { 402219888Sed i += mp->m_length; 403219888Sed fm.source = htobe32(mp->m_char); 404219888Sed fm.destination = htobe16(mp->m_glyph->g_index); 405219888Sed fm.length = htobe16(mp->m_length - 1); 406219888Sed fwrite(&fm, sizeof fm, 1, fp); 407219888Sed } 408219888Sed } 409219888Sed assert(i == j); 410219888Sed} 411219888Sed 412219888Sedstruct file_header { 413219888Sed uint8_t magic[8]; 414219888Sed uint8_t width; 415219888Sed uint8_t height; 416259680Semaste uint16_t pad; 417259680Semaste uint32_t glyph_count; 418259680Semaste uint32_t map_count[4]; 419219888Sed} __packed; 420219888Sed 421219888Sedstatic int 422219888Sedwrite_fnt(const char *filename) 423219888Sed{ 424219888Sed FILE *fp; 425219888Sed struct file_header fh = { 426259680Semaste .magic = "VFNT0002", 427219888Sed }; 428219888Sed 429219888Sed fp = fopen(filename, "wb"); 430219888Sed if (fp == NULL) { 431219888Sed perror(filename); 432219888Sed return (1); 433219888Sed } 434219888Sed 435219888Sed fh.width = width; 436219888Sed fh.height = height; 437259680Semaste fh.glyph_count = htobe32(glyph_unique); 438259680Semaste fh.map_count[0] = htobe32(map_folded_count[0]); 439259680Semaste fh.map_count[1] = htobe32(map_folded_count[1]); 440259680Semaste fh.map_count[2] = htobe32(map_folded_count[2]); 441259680Semaste fh.map_count[3] = htobe32(map_folded_count[3]); 442219888Sed fwrite(&fh, sizeof fh, 1, fp); 443219888Sed 444219888Sed write_glyphs(fp); 445259680Semaste write_mappings(fp, VFNT_MAP_NORMAL); 446219888Sed write_mappings(fp, 1); 447259680Semaste write_mappings(fp, VFNT_MAP_BOLD); 448259680Semaste write_mappings(fp, 3); 449219888Sed 450219888Sed return (0); 451219888Sed} 452219888Sed 453267298Semastestatic void 454267298Semasteprint_font_info(void) 455267298Semaste{ 456267298Semaste printf( 457267298Semaste"Statistics:\n" 458267298Semaste"- glyph_total: %5u\n" 459267298Semaste"- glyph_normal: %5u\n" 460267298Semaste"- glyph_normal_right: %5u\n" 461267298Semaste"- glyph_bold: %5u\n" 462267298Semaste"- glyph_bold_right: %5u\n" 463267298Semaste"- glyph_unique: %5u\n" 464267298Semaste"- glyph_dupe: %5u\n" 465267298Semaste"- mapping_total: %5u\n" 466267298Semaste"- mapping_normal: %5u\n" 467267298Semaste"- mapping_normal_folded: %5u\n" 468267298Semaste"- mapping_normal_right: %5u\n" 469267298Semaste"- mapping_normal_right_folded: %5u\n" 470267298Semaste"- mapping_bold: %5u\n" 471267298Semaste"- mapping_bold_folded: %5u\n" 472267298Semaste"- mapping_bold_right: %5u\n" 473267298Semaste"- mapping_bold_right_folded: %5u\n" 474267298Semaste"- mapping_unique: %5u\n" 475267298Semaste"- mapping_dupe: %5u\n", 476267298Semaste glyph_total, 477267298Semaste glyph_count[0], 478267298Semaste glyph_count[1], 479267298Semaste glyph_count[2], 480267298Semaste glyph_count[3], 481267298Semaste glyph_unique, glyph_dupe, 482267298Semaste mapping_total, 483267298Semaste map_count[0], map_folded_count[0], 484267298Semaste map_count[1], map_folded_count[1], 485267298Semaste map_count[2], map_folded_count[2], 486267298Semaste map_count[3], map_folded_count[3], 487267298Semaste mapping_unique, mapping_dupe); 488267298Semaste} 489267298Semaste 490219888Sedint 491219888Sedmain(int argc, char *argv[]) 492219888Sed{ 493267298Semaste int ch, val, verbose = 0; 494219888Sed 495259680Semaste assert(sizeof(struct file_header) == 32); 496219888Sed assert(sizeof(struct file_mapping) == 8); 497219888Sed 498267011Semaste while ((ch = getopt(argc, argv, "h:w:")) != -1) { 499267011Semaste switch (ch) { 500267011Semaste case 'h': 501267298Semaste val = atoi(optarg); 502267298Semaste if (val <= 0 || val > 128) { 503267298Semaste errx(1, "Invalid height %d", val); 504267298Semaste return (1); 505267298Semaste } 506267298Semaste height = val; 507267011Semaste break; 508267298Semaste case 'v': 509267298Semaste verbose = 1; 510267298Semaste break; 511267011Semaste case 'w': 512267298Semaste val = atoi(optarg); 513267298Semaste if (val <= 0 || val > 128) { 514267298Semaste errx(1, "Invalid width %d", val); 515267298Semaste return (1); 516267298Semaste } 517267298Semaste width = val; 518267011Semaste break; 519267011Semaste case '?': 520267011Semaste default: 521267011Semaste usage(); 522267011Semaste } 523267011Semaste } 524267011Semaste argc -= optind; 525267011Semaste argv += optind; 526267011Semaste 527267012Semaste if (argc < 2 || argc > 3) 528219888Sed usage(); 529267011Semaste 530219888Sed wbytes = howmany(width, 8); 531219888Sed 532267123Semaste if (parse_file(argv[0], VFNT_MAP_NORMAL) != 0) 533219888Sed return (1); 534267012Semaste argc--; 535267012Semaste argv++; 536267012Semaste if (argc == 2) { 537267123Semaste if (parse_file(argv[0], VFNT_MAP_BOLD) != 0) 538267012Semaste return (1); 539267012Semaste argc--; 540267012Semaste argv++; 541267012Semaste } 542219888Sed number_glyphs(); 543219888Sed fold_mappings(0); 544219888Sed fold_mappings(1); 545259680Semaste fold_mappings(2); 546259680Semaste fold_mappings(3); 547267012Semaste if (write_fnt(argv[0]) != 0) 548219888Sed return (1); 549267298Semaste 550267298Semaste if (verbose) 551267298Semaste print_font_info(); 552267298Semaste 553219888Sed return (0); 554219888Sed} 555