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$"); 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> 40267301Semaste#include <err.h> 41219888Sed#include <stdint.h> 42219888Sed#include <stdio.h> 43219888Sed#include <stdlib.h> 44219888Sed#include <string.h> 45267011Semaste#include <unistd.h> 46219888Sed 47259680Semaste#define VFNT_MAPS 4 48259680Semaste#define VFNT_MAP_NORMAL 0 49267301Semaste#define VFNT_MAP_NORMAL_RH 1 50259680Semaste#define VFNT_MAP_BOLD 2 51267301Semaste#define VFNT_MAP_BOLD_RH 3 52259680Semaste 53267011Semastestatic unsigned int width = 8, wbytes, height = 16; 54219888Sed 55219888Sedstruct glyph { 56219888Sed TAILQ_ENTRY(glyph) g_list; 57267035Semaste SLIST_ENTRY(glyph) g_hash; 58219888Sed uint8_t *g_data; 59219888Sed unsigned int g_index; 60219888Sed}; 61219888Sed 62267035Semaste#define FONTCVT_NHASH 4096 63259680SemasteTAILQ_HEAD(glyph_list, glyph); 64267035Semastestatic SLIST_HEAD(, glyph) glyph_hash[FONTCVT_NHASH]; 65259680Semastestatic struct glyph_list glyphs[VFNT_MAPS] = { 66259680Semaste TAILQ_HEAD_INITIALIZER(glyphs[0]), 67259680Semaste TAILQ_HEAD_INITIALIZER(glyphs[1]), 68259680Semaste TAILQ_HEAD_INITIALIZER(glyphs[2]), 69259680Semaste TAILQ_HEAD_INITIALIZER(glyphs[3]), 70259680Semaste}; 71259680Semastestatic unsigned int glyph_total, glyph_count[4], glyph_unique, glyph_dupe; 72219888Sed 73219888Sedstruct mapping { 74219888Sed TAILQ_ENTRY(mapping) m_list; 75219888Sed unsigned int m_char; 76219888Sed unsigned int m_length; 77219888Sed struct glyph *m_glyph; 78219888Sed}; 79219888Sed 80219888SedTAILQ_HEAD(mapping_list, mapping); 81259680Semastestatic struct mapping_list maps[VFNT_MAPS] = { 82259680Semaste TAILQ_HEAD_INITIALIZER(maps[0]), 83259680Semaste TAILQ_HEAD_INITIALIZER(maps[1]), 84259680Semaste TAILQ_HEAD_INITIALIZER(maps[2]), 85259680Semaste TAILQ_HEAD_INITIALIZER(maps[3]), 86259680Semaste}; 87259680Semastestatic unsigned int mapping_total, map_count[4], map_folded_count[4], 88259680Semaste mapping_unique, mapping_dupe; 89219888Sed 90219888Sedstatic void 91219888Sedusage(void) 92219888Sed{ 93219888Sed 94269041Semaste (void)fprintf(stderr, 95267337Semaste"usage: vtfontcvt [-w width] [-h height] [-v] normal.bdf [bold.bdf] out.fnt\n"); 96219888Sed exit(1); 97219888Sed} 98219888Sed 99219888Sedstatic int 100259680Semasteadd_mapping(struct glyph *gl, unsigned int c, unsigned int map_idx) 101219888Sed{ 102219888Sed struct mapping *mp; 103219888Sed struct mapping_list *ml; 104219888Sed 105219888Sed mapping_total++; 106219888Sed 107219888Sed mp = malloc(sizeof *mp); 108219888Sed mp->m_char = c; 109219888Sed mp->m_glyph = gl; 110219888Sed mp->m_length = 0; 111219888Sed 112259680Semaste ml = &maps[map_idx]; 113219888Sed if (TAILQ_LAST(ml, mapping_list) != NULL && 114269041Semaste TAILQ_LAST(ml, mapping_list)->m_char >= c) 115267298Semaste errx(1, "Bad ordering at character %u\n", c); 116219888Sed TAILQ_INSERT_TAIL(ml, mp, m_list); 117219888Sed 118259680Semaste map_count[map_idx]++; 119219888Sed mapping_unique++; 120219888Sed 121219888Sed return (0); 122219888Sed} 123219888Sed 124267301Semastestatic int 125267301Semastededup_mapping(unsigned int map_idx) 126267301Semaste{ 127267301Semaste struct mapping *mp_bold, *mp_normal, *mp_temp; 128267301Semaste unsigned normal_map_idx = map_idx - VFNT_MAP_BOLD; 129267301Semaste 130267301Semaste assert(map_idx == VFNT_MAP_BOLD || map_idx == VFNT_MAP_BOLD_RH); 131267301Semaste mp_normal = TAILQ_FIRST(&maps[normal_map_idx]); 132267301Semaste TAILQ_FOREACH_SAFE(mp_bold, &maps[map_idx], m_list, mp_temp) { 133267301Semaste while (mp_normal->m_char < mp_bold->m_char) 134267301Semaste mp_normal = TAILQ_NEXT(mp_normal, m_list); 135269041Semaste if (mp_bold->m_char != mp_normal->m_char) 136267301Semaste errx(1, "Character %u not in normal font!\n", 137267301Semaste mp_bold->m_char); 138267301Semaste if (mp_bold->m_glyph != mp_normal->m_glyph) 139267301Semaste continue; 140267301Semaste 141267301Semaste /* No mapping is needed if it's equal to the normal mapping. */ 142267301Semaste TAILQ_REMOVE(&maps[map_idx], mp_bold, m_list); 143267301Semaste free(mp_bold); 144267301Semaste mapping_dupe++; 145267301Semaste } 146267301Semaste return (0); 147267301Semaste} 148267301Semaste 149219888Sedstatic struct glyph * 150259680Semasteadd_glyph(const uint8_t *bytes, unsigned int map_idx, int fallback) 151219888Sed{ 152219888Sed struct glyph *gl; 153267035Semaste int hash; 154219888Sed 155219888Sed glyph_total++; 156259680Semaste glyph_count[map_idx]++; 157219888Sed 158267035Semaste hash = fnv_32_buf(bytes, wbytes * height, FNV1_32_INIT) % FONTCVT_NHASH; 159267035Semaste SLIST_FOREACH(gl, &glyph_hash[hash], g_hash) { 160267035Semaste if (memcmp(gl->g_data, bytes, wbytes * height) == 0) { 161267035Semaste glyph_dupe++; 162267035Semaste return (gl); 163219888Sed } 164219888Sed } 165219888Sed 166219888Sed gl = malloc(sizeof *gl); 167219888Sed gl->g_data = malloc(wbytes * height); 168219888Sed memcpy(gl->g_data, bytes, wbytes * height); 169219888Sed if (fallback) 170259680Semaste TAILQ_INSERT_HEAD(&glyphs[map_idx], gl, g_list); 171219888Sed else 172259680Semaste TAILQ_INSERT_TAIL(&glyphs[map_idx], gl, g_list); 173267035Semaste SLIST_INSERT_HEAD(&glyph_hash[hash], gl, g_hash); 174219888Sed 175219888Sed glyph_unique++; 176219888Sed return (gl); 177219888Sed} 178219888Sed 179219888Sedstatic int 180267123Semasteadd_char(unsigned curchar, unsigned map_idx, uint8_t *bytes, uint8_t *bytes_r) 181267123Semaste{ 182267123Semaste struct glyph *gl; 183267123Semaste 184267123Semaste /* Prevent adding two glyphs for 0xFFFD */ 185267123Semaste if (curchar == 0xFFFD) { 186267123Semaste if (map_idx < VFNT_MAP_BOLD) 187267123Semaste gl = add_glyph(bytes, 0, 1); 188267123Semaste } else if (curchar >= 0x20) { 189267123Semaste gl = add_glyph(bytes, map_idx, 0); 190267123Semaste if (add_mapping(gl, curchar, map_idx) != 0) 191267123Semaste return (1); 192267123Semaste if (bytes_r != NULL) { 193267123Semaste gl = add_glyph(bytes_r, map_idx + 1, 0); 194267123Semaste if (add_mapping(gl, curchar, 195267123Semaste map_idx + 1) != 0) 196267123Semaste return (1); 197267123Semaste } 198267123Semaste } 199267123Semaste return (0); 200267123Semaste} 201267123Semaste 202267123Semaste 203267123Semastestatic int 204259680Semasteparse_bitmap_line(uint8_t *left, uint8_t *right, unsigned int line, 205259680Semaste unsigned int dwidth) 206219888Sed{ 207259680Semaste uint8_t *p; 208259680Semaste unsigned int i, subline; 209259680Semaste 210269041Semaste if (dwidth != width && dwidth != width * 2) 211269041Semaste errx(1, "Bitmap with unsupported width %u!\n", dwidth); 212259680Semaste 213259680Semaste /* Move pixel data right to simplify splitting double characters. */ 214259680Semaste line >>= (howmany(dwidth, 8) * 8) - dwidth; 215259680Semaste 216259680Semaste for (i = dwidth / width; i > 0; i--) { 217259680Semaste p = (i == 2) ? right : left; 218259680Semaste 219259680Semaste subline = line & ((1 << width) - 1); 220259680Semaste subline <<= (howmany(width, 8) * 8) - width; 221259680Semaste 222259680Semaste if (wbytes == 1) { 223259680Semaste *p = subline; 224259680Semaste } else if (wbytes == 2) { 225259680Semaste *p++ = subline >> 8; 226259680Semaste *p = subline; 227259680Semaste } else { 228269041Semaste errx(1, "Unsupported wbytes %u!\n", wbytes); 229259680Semaste } 230259680Semaste 231259680Semaste line >>= width; 232259680Semaste } 233267337Semaste 234259680Semaste return (0); 235259680Semaste} 236259680Semaste 237259680Semastestatic int 238267123Semasteparse_bdf(FILE *fp, unsigned int map_idx) 239259680Semaste{ 240219888Sed char *ln; 241219888Sed size_t length; 242259680Semaste uint8_t bytes[wbytes * height], bytes_r[wbytes * height]; 243259680Semaste unsigned int curchar = 0, dwidth = 0, i, line; 244219888Sed 245219888Sed while ((ln = fgetln(fp, &length)) != NULL) { 246219888Sed ln[length - 1] = '\0'; 247219888Sed 248219888Sed if (strncmp(ln, "ENCODING ", 9) == 0) { 249219888Sed curchar = atoi(ln + 9); 250219888Sed } 251219888Sed 252259680Semaste if (strncmp(ln, "DWIDTH ", 7) == 0) { 253259680Semaste dwidth = atoi(ln + 7); 254259680Semaste } 255259680Semaste 256267126Semaste if (strncmp(ln, "BITMAP", 6) == 0 && 257267126Semaste (ln[6] == ' ' || ln[6] == '\0')) { 258219888Sed for (i = 0; i < height; i++) { 259269041Semaste if ((ln = fgetln(fp, &length)) == NULL) 260267298Semaste errx(1, "Unexpected EOF!\n"); 261219888Sed ln[length - 1] = '\0'; 262219888Sed sscanf(ln, "%x", &line); 263259680Semaste if (parse_bitmap_line(bytes + i * wbytes, 264259680Semaste bytes_r + i * wbytes, line, dwidth) != 0) 265219888Sed return (1); 266219888Sed } 267219888Sed 268267123Semaste if (add_char(curchar, map_idx, bytes, 269267123Semaste dwidth == width * 2 ? bytes_r : NULL) != 0) 270267123Semaste return (1); 271267123Semaste } 272267123Semaste } 273267123Semaste 274267123Semaste return (0); 275267123Semaste} 276267123Semaste 277269041Semastestatic void 278269041Semasteset_width(int w) 279269041Semaste{ 280269041Semaste 281269041Semaste if (w <= 0 || w > 128) 282269041Semaste errx(1, "invalid width %d", w); 283269041Semaste width = w; 284269041Semaste wbytes = howmany(width, 8); 285269041Semaste} 286269041Semaste 287267123Semastestatic int 288267123Semasteparse_hex(FILE *fp, unsigned int map_idx) 289267123Semaste{ 290267123Semaste char *ln, *p; 291267123Semaste char fmt_str[8]; 292267123Semaste size_t length; 293267123Semaste uint8_t bytes[wbytes * height], bytes_r[wbytes * height]; 294267123Semaste unsigned curchar = 0, i, line, chars_per_row, dwidth; 295267123Semaste 296267123Semaste while ((ln = fgetln(fp, &length)) != NULL) { 297267123Semaste ln[length - 1] = '\0'; 298267123Semaste 299267123Semaste if (strncmp(ln, "# Height: ", 10) == 0) { 300267123Semaste height = atoi(ln + 10); 301267123Semaste } else if (strncmp(ln, "# Width: ", 9) == 0) { 302269041Semaste set_width(atoi(ln + 9)); 303267123Semaste } else if (sscanf(ln, "%4x:", &curchar)) { 304267123Semaste p = ln + 5; 305267123Semaste chars_per_row = strlen(p) / height; 306267123Semaste dwidth = width; 307269041Semaste if (chars_per_row / 2 > (width + 7) / 8) 308267123Semaste dwidth *= 2; /* Double-width character. */ 309267123Semaste snprintf(fmt_str, sizeof(fmt_str), "%%%ux", 310267123Semaste chars_per_row); 311267337Semaste 312267123Semaste for (i = 0; i < height; i++) { 313267123Semaste sscanf(p, fmt_str, &line); 314267123Semaste p += chars_per_row; 315267123Semaste if (parse_bitmap_line(bytes + i * wbytes, 316267123Semaste bytes_r + i * wbytes, line, dwidth) != 0) 317219888Sed return (1); 318219888Sed } 319267123Semaste 320267123Semaste if (add_char(curchar, map_idx, bytes, 321267123Semaste dwidth == width * 2 ? bytes_r : NULL) != 0) 322267123Semaste return (1); 323219888Sed } 324219888Sed } 325219888Sed return (0); 326219888Sed} 327219888Sed 328267123Semastestatic int 329267123Semasteparse_file(const char *filename, unsigned int map_idx) 330267123Semaste{ 331267123Semaste FILE *fp; 332267123Semaste size_t len; 333269041Semaste int rv; 334267123Semaste 335267123Semaste fp = fopen(filename, "r"); 336267123Semaste if (fp == NULL) { 337267123Semaste perror(filename); 338267123Semaste return (1); 339267123Semaste } 340267123Semaste len = strlen(filename); 341267123Semaste if (len > 4 && strcasecmp(filename + len - 4, ".hex") == 0) 342269041Semaste rv = parse_hex(fp, map_idx); 343269041Semaste else 344269041Semaste rv = parse_bdf(fp, map_idx); 345269041Semaste fclose(fp); 346269041Semaste return (rv); 347267123Semaste} 348267123Semaste 349219888Sedstatic void 350219888Sednumber_glyphs(void) 351219888Sed{ 352219888Sed struct glyph *gl; 353259680Semaste unsigned int i, idx = 0; 354219888Sed 355259680Semaste for (i = 0; i < VFNT_MAPS; i++) 356259680Semaste TAILQ_FOREACH(gl, &glyphs[i], g_list) 357259680Semaste gl->g_index = idx++; 358219888Sed} 359219888Sed 360267324Semastestatic int 361219888Sedwrite_glyphs(FILE *fp) 362219888Sed{ 363219888Sed struct glyph *gl; 364259680Semaste unsigned int i; 365219888Sed 366259680Semaste for (i = 0; i < VFNT_MAPS; i++) { 367259680Semaste TAILQ_FOREACH(gl, &glyphs[i], g_list) 368267324Semaste if (fwrite(gl->g_data, wbytes * height, 1, fp) != 1) 369267324Semaste return (1); 370259680Semaste } 371267324Semaste return (0); 372219888Sed} 373219888Sed 374219888Sedstatic void 375259680Semastefold_mappings(unsigned int map_idx) 376219888Sed{ 377259680Semaste struct mapping_list *ml = &maps[map_idx]; 378219888Sed struct mapping *mn, *mp, *mbase; 379219888Sed 380219888Sed mp = mbase = TAILQ_FIRST(ml); 381219888Sed for (mp = mbase = TAILQ_FIRST(ml); mp != NULL; mp = mn) { 382219888Sed mn = TAILQ_NEXT(mp, m_list); 383219888Sed if (mn != NULL && mn->m_char == mp->m_char + 1 && 384219888Sed mn->m_glyph->g_index == mp->m_glyph->g_index + 1) 385219888Sed continue; 386219888Sed mbase->m_length = mp->m_char - mbase->m_char + 1; 387219888Sed mbase = mp = mn; 388259680Semaste map_folded_count[map_idx]++; 389219888Sed } 390219888Sed} 391219888Sed 392219888Sedstruct file_mapping { 393219888Sed uint32_t source; 394219888Sed uint16_t destination; 395219888Sed uint16_t length; 396219888Sed} __packed; 397219888Sed 398267324Semastestatic int 399259680Semastewrite_mappings(FILE *fp, unsigned int map_idx) 400219888Sed{ 401259680Semaste struct mapping_list *ml = &maps[map_idx]; 402219888Sed struct mapping *mp; 403219888Sed struct file_mapping fm; 404219888Sed unsigned int i = 0, j = 0; 405219888Sed 406219888Sed TAILQ_FOREACH(mp, ml, m_list) { 407219888Sed j++; 408219888Sed if (mp->m_length > 0) { 409219888Sed i += mp->m_length; 410219888Sed fm.source = htobe32(mp->m_char); 411219888Sed fm.destination = htobe16(mp->m_glyph->g_index); 412219888Sed fm.length = htobe16(mp->m_length - 1); 413267324Semaste if (fwrite(&fm, sizeof fm, 1, fp) != 1) 414267324Semaste return (1); 415219888Sed } 416219888Sed } 417219888Sed assert(i == j); 418267324Semaste return (0); 419219888Sed} 420219888Sed 421219888Sedstruct file_header { 422219888Sed uint8_t magic[8]; 423219888Sed uint8_t width; 424219888Sed uint8_t height; 425259680Semaste uint16_t pad; 426259680Semaste uint32_t glyph_count; 427259680Semaste uint32_t map_count[4]; 428219888Sed} __packed; 429219888Sed 430219888Sedstatic int 431219888Sedwrite_fnt(const char *filename) 432219888Sed{ 433219888Sed FILE *fp; 434219888Sed struct file_header fh = { 435259680Semaste .magic = "VFNT0002", 436219888Sed }; 437219888Sed 438219888Sed fp = fopen(filename, "wb"); 439219888Sed if (fp == NULL) { 440219888Sed perror(filename); 441219888Sed return (1); 442219888Sed } 443219888Sed 444219888Sed fh.width = width; 445219888Sed fh.height = height; 446259680Semaste fh.glyph_count = htobe32(glyph_unique); 447259680Semaste fh.map_count[0] = htobe32(map_folded_count[0]); 448259680Semaste fh.map_count[1] = htobe32(map_folded_count[1]); 449259680Semaste fh.map_count[2] = htobe32(map_folded_count[2]); 450259680Semaste fh.map_count[3] = htobe32(map_folded_count[3]); 451267324Semaste if (fwrite(&fh, sizeof fh, 1, fp) != 1) { 452267324Semaste perror(filename); 453269041Semaste fclose(fp); 454267324Semaste return (1); 455267324Semaste } 456267337Semaste 457267324Semaste if (write_glyphs(fp) != 0 || 458267324Semaste write_mappings(fp, VFNT_MAP_NORMAL) != 0 || 459267324Semaste write_mappings(fp, 1) != 0 || 460267324Semaste write_mappings(fp, VFNT_MAP_BOLD) != 0 || 461267324Semaste write_mappings(fp, 3) != 0) { 462267324Semaste perror(filename); 463269041Semaste fclose(fp); 464267324Semaste return (1); 465267324Semaste } 466219888Sed 467269041Semaste fclose(fp); 468219888Sed return (0); 469219888Sed} 470219888Sed 471267298Semastestatic void 472267298Semasteprint_font_info(void) 473267298Semaste{ 474267298Semaste printf( 475267298Semaste"Statistics:\n" 476267298Semaste"- glyph_total: %5u\n" 477267298Semaste"- glyph_normal: %5u\n" 478267298Semaste"- glyph_normal_right: %5u\n" 479267298Semaste"- glyph_bold: %5u\n" 480267298Semaste"- glyph_bold_right: %5u\n" 481267298Semaste"- glyph_unique: %5u\n" 482267298Semaste"- glyph_dupe: %5u\n" 483267298Semaste"- mapping_total: %5u\n" 484267298Semaste"- mapping_normal: %5u\n" 485267298Semaste"- mapping_normal_folded: %5u\n" 486267298Semaste"- mapping_normal_right: %5u\n" 487267298Semaste"- mapping_normal_right_folded: %5u\n" 488267298Semaste"- mapping_bold: %5u\n" 489267298Semaste"- mapping_bold_folded: %5u\n" 490267298Semaste"- mapping_bold_right: %5u\n" 491267298Semaste"- mapping_bold_right_folded: %5u\n" 492267298Semaste"- mapping_unique: %5u\n" 493267298Semaste"- mapping_dupe: %5u\n", 494267298Semaste glyph_total, 495267298Semaste glyph_count[0], 496267298Semaste glyph_count[1], 497267298Semaste glyph_count[2], 498267298Semaste glyph_count[3], 499267298Semaste glyph_unique, glyph_dupe, 500267298Semaste mapping_total, 501267298Semaste map_count[0], map_folded_count[0], 502267298Semaste map_count[1], map_folded_count[1], 503267298Semaste map_count[2], map_folded_count[2], 504267298Semaste map_count[3], map_folded_count[3], 505267298Semaste mapping_unique, mapping_dupe); 506267298Semaste} 507267298Semaste 508219888Sedint 509219888Sedmain(int argc, char *argv[]) 510219888Sed{ 511267298Semaste int ch, val, verbose = 0; 512219888Sed 513259680Semaste assert(sizeof(struct file_header) == 32); 514219888Sed assert(sizeof(struct file_mapping) == 8); 515219888Sed 516267337Semaste while ((ch = getopt(argc, argv, "h:vw:")) != -1) { 517267011Semaste switch (ch) { 518267011Semaste case 'h': 519267298Semaste val = atoi(optarg); 520269041Semaste if (val <= 0 || val > 128) 521267298Semaste errx(1, "Invalid height %d", val); 522267298Semaste height = val; 523267011Semaste break; 524267298Semaste case 'v': 525267298Semaste verbose = 1; 526267298Semaste break; 527267011Semaste case 'w': 528269041Semaste set_width(atoi(optarg)); 529267011Semaste break; 530267011Semaste case '?': 531267011Semaste default: 532267011Semaste usage(); 533267011Semaste } 534267011Semaste } 535267011Semaste argc -= optind; 536267011Semaste argv += optind; 537267011Semaste 538267012Semaste if (argc < 2 || argc > 3) 539219888Sed usage(); 540267011Semaste 541219888Sed wbytes = howmany(width, 8); 542219888Sed 543267123Semaste if (parse_file(argv[0], VFNT_MAP_NORMAL) != 0) 544219888Sed return (1); 545267012Semaste argc--; 546267012Semaste argv++; 547267012Semaste if (argc == 2) { 548267123Semaste if (parse_file(argv[0], VFNT_MAP_BOLD) != 0) 549267012Semaste return (1); 550267012Semaste argc--; 551267012Semaste argv++; 552267012Semaste } 553219888Sed number_glyphs(); 554267301Semaste dedup_mapping(VFNT_MAP_BOLD); 555267301Semaste dedup_mapping(VFNT_MAP_BOLD_RH); 556219888Sed fold_mappings(0); 557219888Sed fold_mappings(1); 558259680Semaste fold_mappings(2); 559259680Semaste fold_mappings(3); 560267012Semaste if (write_fnt(argv[0]) != 0) 561219888Sed return (1); 562267298Semaste 563267298Semaste if (verbose) 564267298Semaste print_font_info(); 565267298Semaste 566219888Sed return (0); 567219888Sed} 568