vtfontcvt.c revision 267337
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/usr.bin/vtfontcvt/vtfontcvt.c 267337 2014-06-10 18:29:45Z 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> 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 94267298Semaste errx(1, 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 && 114219888Sed TAILQ_LAST(ml, mapping_list)->m_char >= c) { 115267298Semaste errx(1, "Bad ordering at character %u\n", c); 116219888Sed return (1); 117219888Sed } 118219888Sed TAILQ_INSERT_TAIL(ml, mp, m_list); 119219888Sed 120259680Semaste map_count[map_idx]++; 121219888Sed mapping_unique++; 122219888Sed 123219888Sed return (0); 124219888Sed} 125219888Sed 126267301Semastestatic int 127267301Semastededup_mapping(unsigned int map_idx) 128267301Semaste{ 129267301Semaste struct mapping *mp_bold, *mp_normal, *mp_temp; 130267301Semaste unsigned normal_map_idx = map_idx - VFNT_MAP_BOLD; 131267301Semaste 132267301Semaste assert(map_idx == VFNT_MAP_BOLD || map_idx == VFNT_MAP_BOLD_RH); 133267301Semaste mp_normal = TAILQ_FIRST(&maps[normal_map_idx]); 134267301Semaste TAILQ_FOREACH_SAFE(mp_bold, &maps[map_idx], m_list, mp_temp) { 135267301Semaste while (mp_normal->m_char < mp_bold->m_char) 136267301Semaste mp_normal = TAILQ_NEXT(mp_normal, m_list); 137267301Semaste if (mp_bold->m_char != mp_normal->m_char) { 138267301Semaste errx(1, "Character %u not in normal font!\n", 139267301Semaste mp_bold->m_char); 140267301Semaste return (1); 141267301Semaste } 142267301Semaste if (mp_bold->m_glyph != mp_normal->m_glyph) 143267301Semaste continue; 144267301Semaste 145267301Semaste /* No mapping is needed if it's equal to the normal mapping. */ 146267301Semaste TAILQ_REMOVE(&maps[map_idx], mp_bold, m_list); 147267301Semaste free(mp_bold); 148267301Semaste mapping_dupe++; 149267301Semaste } 150267301Semaste return (0); 151267301Semaste} 152267301Semaste 153219888Sedstatic struct glyph * 154259680Semasteadd_glyph(const uint8_t *bytes, unsigned int map_idx, int fallback) 155219888Sed{ 156219888Sed struct glyph *gl; 157267035Semaste int hash; 158219888Sed 159219888Sed glyph_total++; 160259680Semaste glyph_count[map_idx]++; 161219888Sed 162267035Semaste hash = fnv_32_buf(bytes, wbytes * height, FNV1_32_INIT) % FONTCVT_NHASH; 163267035Semaste SLIST_FOREACH(gl, &glyph_hash[hash], g_hash) { 164267035Semaste if (memcmp(gl->g_data, bytes, wbytes * height) == 0) { 165267035Semaste glyph_dupe++; 166267035Semaste return (gl); 167219888Sed } 168219888Sed } 169219888Sed 170219888Sed gl = malloc(sizeof *gl); 171219888Sed gl->g_data = malloc(wbytes * height); 172219888Sed memcpy(gl->g_data, bytes, wbytes * height); 173219888Sed if (fallback) 174259680Semaste TAILQ_INSERT_HEAD(&glyphs[map_idx], gl, g_list); 175219888Sed else 176259680Semaste TAILQ_INSERT_TAIL(&glyphs[map_idx], gl, g_list); 177267035Semaste SLIST_INSERT_HEAD(&glyph_hash[hash], gl, g_hash); 178219888Sed 179219888Sed glyph_unique++; 180219888Sed return (gl); 181219888Sed} 182219888Sed 183219888Sedstatic int 184267123Semasteadd_char(unsigned curchar, unsigned map_idx, uint8_t *bytes, uint8_t *bytes_r) 185267123Semaste{ 186267123Semaste struct glyph *gl; 187267123Semaste 188267123Semaste /* Prevent adding two glyphs for 0xFFFD */ 189267123Semaste if (curchar == 0xFFFD) { 190267123Semaste if (map_idx < VFNT_MAP_BOLD) 191267123Semaste gl = add_glyph(bytes, 0, 1); 192267123Semaste } else if (curchar >= 0x20) { 193267123Semaste gl = add_glyph(bytes, map_idx, 0); 194267123Semaste if (add_mapping(gl, curchar, map_idx) != 0) 195267123Semaste return (1); 196267123Semaste if (bytes_r != NULL) { 197267123Semaste gl = add_glyph(bytes_r, map_idx + 1, 0); 198267123Semaste if (add_mapping(gl, curchar, 199267123Semaste map_idx + 1) != 0) 200267123Semaste return (1); 201267123Semaste } 202267123Semaste } 203267123Semaste return (0); 204267123Semaste} 205267123Semaste 206267123Semaste 207267123Semastestatic int 208259680Semasteparse_bitmap_line(uint8_t *left, uint8_t *right, unsigned int line, 209259680Semaste unsigned int dwidth) 210219888Sed{ 211259680Semaste uint8_t *p; 212259680Semaste unsigned int i, subline; 213259680Semaste 214259680Semaste if (dwidth != width && dwidth != width * 2) { 215267298Semaste errx(1, 216267298Semaste "Bitmap with unsupported width %u!\n", dwidth); 217259680Semaste return (1); 218259680Semaste } 219259680Semaste 220259680Semaste /* Move pixel data right to simplify splitting double characters. */ 221259680Semaste line >>= (howmany(dwidth, 8) * 8) - dwidth; 222259680Semaste 223259680Semaste for (i = dwidth / width; i > 0; i--) { 224259680Semaste p = (i == 2) ? right : left; 225259680Semaste 226259680Semaste subline = line & ((1 << width) - 1); 227259680Semaste subline <<= (howmany(width, 8) * 8) - width; 228259680Semaste 229259680Semaste if (wbytes == 1) { 230259680Semaste *p = subline; 231259680Semaste } else if (wbytes == 2) { 232259680Semaste *p++ = subline >> 8; 233259680Semaste *p = subline; 234259680Semaste } else { 235267298Semaste errx(1, 236259680Semaste "Unsupported wbytes %u!\n", wbytes); 237259680Semaste return (1); 238259680Semaste } 239259680Semaste 240259680Semaste line >>= width; 241259680Semaste } 242267337Semaste 243259680Semaste return (0); 244259680Semaste} 245259680Semaste 246259680Semastestatic int 247267123Semasteparse_bdf(FILE *fp, unsigned int map_idx) 248259680Semaste{ 249219888Sed char *ln; 250219888Sed size_t length; 251259680Semaste uint8_t bytes[wbytes * height], bytes_r[wbytes * height]; 252259680Semaste unsigned int curchar = 0, dwidth = 0, i, line; 253219888Sed 254219888Sed while ((ln = fgetln(fp, &length)) != NULL) { 255219888Sed ln[length - 1] = '\0'; 256219888Sed 257219888Sed if (strncmp(ln, "ENCODING ", 9) == 0) { 258219888Sed curchar = atoi(ln + 9); 259219888Sed } 260219888Sed 261259680Semaste if (strncmp(ln, "DWIDTH ", 7) == 0) { 262259680Semaste dwidth = atoi(ln + 7); 263259680Semaste } 264259680Semaste 265267126Semaste if (strncmp(ln, "BITMAP", 6) == 0 && 266267126Semaste (ln[6] == ' ' || ln[6] == '\0')) { 267219888Sed for (i = 0; i < height; i++) { 268219888Sed if ((ln = fgetln(fp, &length)) == NULL) { 269267298Semaste errx(1, "Unexpected EOF!\n"); 270219888Sed return (1); 271219888Sed } 272219888Sed ln[length - 1] = '\0'; 273219888Sed sscanf(ln, "%x", &line); 274259680Semaste if (parse_bitmap_line(bytes + i * wbytes, 275259680Semaste bytes_r + i * wbytes, line, dwidth) != 0) 276219888Sed return (1); 277219888Sed } 278219888Sed 279267123Semaste if (add_char(curchar, map_idx, bytes, 280267123Semaste dwidth == width * 2 ? bytes_r : NULL) != 0) 281267123Semaste return (1); 282267123Semaste } 283267123Semaste } 284267123Semaste 285267123Semaste return (0); 286267123Semaste} 287267123Semaste 288267123Semastestatic int 289267123Semasteparse_hex(FILE *fp, unsigned int map_idx) 290267123Semaste{ 291267123Semaste char *ln, *p; 292267123Semaste char fmt_str[8]; 293267123Semaste size_t length; 294267123Semaste uint8_t bytes[wbytes * height], bytes_r[wbytes * height]; 295267123Semaste unsigned curchar = 0, i, line, chars_per_row, dwidth; 296267123Semaste 297267123Semaste while ((ln = fgetln(fp, &length)) != NULL) { 298267123Semaste ln[length - 1] = '\0'; 299267123Semaste 300267123Semaste if (strncmp(ln, "# Height: ", 10) == 0) { 301267123Semaste height = atoi(ln + 10); 302267123Semaste } else if (strncmp(ln, "# Width: ", 9) == 0) { 303267123Semaste width = atoi(ln + 9); 304267123Semaste } else if (sscanf(ln, "%4x:", &curchar)) { 305267123Semaste p = ln + 5; 306267123Semaste chars_per_row = strlen(p) / height; 307267123Semaste dwidth = width; 308267123Semaste if (chars_per_row / 2 > width / 8) 309267123Semaste dwidth *= 2; /* Double-width character. */ 310267123Semaste snprintf(fmt_str, sizeof(fmt_str), "%%%ux", 311267123Semaste chars_per_row); 312267337Semaste 313267123Semaste for (i = 0; i < height; i++) { 314267123Semaste sscanf(p, fmt_str, &line); 315267123Semaste p += chars_per_row; 316267123Semaste if (parse_bitmap_line(bytes + i * wbytes, 317267123Semaste bytes_r + i * wbytes, line, dwidth) != 0) 318219888Sed return (1); 319219888Sed } 320267123Semaste 321267123Semaste if (add_char(curchar, map_idx, bytes, 322267123Semaste dwidth == width * 2 ? bytes_r : NULL) != 0) 323267123Semaste return (1); 324219888Sed } 325219888Sed } 326219888Sed return (0); 327219888Sed} 328219888Sed 329267123Semastestatic int 330267123Semasteparse_file(const char *filename, unsigned int map_idx) 331267123Semaste{ 332267123Semaste FILE *fp; 333267123Semaste size_t len; 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) 342267123Semaste return parse_hex(fp, map_idx); 343267123Semaste return parse_bdf(fp, map_idx); 344267123Semaste} 345267123Semaste 346219888Sedstatic void 347219888Sednumber_glyphs(void) 348219888Sed{ 349219888Sed struct glyph *gl; 350259680Semaste unsigned int i, idx = 0; 351219888Sed 352259680Semaste for (i = 0; i < VFNT_MAPS; i++) 353259680Semaste TAILQ_FOREACH(gl, &glyphs[i], g_list) 354259680Semaste gl->g_index = idx++; 355219888Sed} 356219888Sed 357267324Semastestatic int 358219888Sedwrite_glyphs(FILE *fp) 359219888Sed{ 360219888Sed struct glyph *gl; 361259680Semaste unsigned int i; 362219888Sed 363259680Semaste for (i = 0; i < VFNT_MAPS; i++) { 364259680Semaste TAILQ_FOREACH(gl, &glyphs[i], g_list) 365267324Semaste if (fwrite(gl->g_data, wbytes * height, 1, fp) != 1) 366267324Semaste return (1); 367259680Semaste } 368267324Semaste return (0); 369219888Sed} 370219888Sed 371219888Sedstatic void 372259680Semastefold_mappings(unsigned int map_idx) 373219888Sed{ 374259680Semaste struct mapping_list *ml = &maps[map_idx]; 375219888Sed struct mapping *mn, *mp, *mbase; 376219888Sed 377219888Sed mp = mbase = TAILQ_FIRST(ml); 378219888Sed for (mp = mbase = TAILQ_FIRST(ml); mp != NULL; mp = mn) { 379219888Sed mn = TAILQ_NEXT(mp, m_list); 380219888Sed if (mn != NULL && mn->m_char == mp->m_char + 1 && 381219888Sed mn->m_glyph->g_index == mp->m_glyph->g_index + 1) 382219888Sed continue; 383219888Sed mbase->m_length = mp->m_char - mbase->m_char + 1; 384219888Sed mbase = mp = mn; 385259680Semaste map_folded_count[map_idx]++; 386219888Sed } 387219888Sed} 388219888Sed 389219888Sedstruct file_mapping { 390219888Sed uint32_t source; 391219888Sed uint16_t destination; 392219888Sed uint16_t length; 393219888Sed} __packed; 394219888Sed 395267324Semastestatic int 396259680Semastewrite_mappings(FILE *fp, unsigned int map_idx) 397219888Sed{ 398259680Semaste struct mapping_list *ml = &maps[map_idx]; 399219888Sed struct mapping *mp; 400219888Sed struct file_mapping fm; 401219888Sed unsigned int i = 0, j = 0; 402219888Sed 403219888Sed TAILQ_FOREACH(mp, ml, m_list) { 404219888Sed j++; 405219888Sed if (mp->m_length > 0) { 406219888Sed i += mp->m_length; 407219888Sed fm.source = htobe32(mp->m_char); 408219888Sed fm.destination = htobe16(mp->m_glyph->g_index); 409219888Sed fm.length = htobe16(mp->m_length - 1); 410267324Semaste if (fwrite(&fm, sizeof fm, 1, fp) != 1) 411267324Semaste return (1); 412219888Sed } 413219888Sed } 414219888Sed assert(i == j); 415267324Semaste return (0); 416219888Sed} 417219888Sed 418219888Sedstruct file_header { 419219888Sed uint8_t magic[8]; 420219888Sed uint8_t width; 421219888Sed uint8_t height; 422259680Semaste uint16_t pad; 423259680Semaste uint32_t glyph_count; 424259680Semaste uint32_t map_count[4]; 425219888Sed} __packed; 426219888Sed 427219888Sedstatic int 428219888Sedwrite_fnt(const char *filename) 429219888Sed{ 430219888Sed FILE *fp; 431219888Sed struct file_header fh = { 432259680Semaste .magic = "VFNT0002", 433219888Sed }; 434219888Sed 435219888Sed fp = fopen(filename, "wb"); 436219888Sed if (fp == NULL) { 437219888Sed perror(filename); 438219888Sed return (1); 439219888Sed } 440219888Sed 441219888Sed fh.width = width; 442219888Sed fh.height = height; 443259680Semaste fh.glyph_count = htobe32(glyph_unique); 444259680Semaste fh.map_count[0] = htobe32(map_folded_count[0]); 445259680Semaste fh.map_count[1] = htobe32(map_folded_count[1]); 446259680Semaste fh.map_count[2] = htobe32(map_folded_count[2]); 447259680Semaste fh.map_count[3] = htobe32(map_folded_count[3]); 448267324Semaste if (fwrite(&fh, sizeof fh, 1, fp) != 1) { 449267324Semaste perror(filename); 450267324Semaste return (1); 451267324Semaste } 452267337Semaste 453267324Semaste if (write_glyphs(fp) != 0 || 454267324Semaste write_mappings(fp, VFNT_MAP_NORMAL) != 0 || 455267324Semaste write_mappings(fp, 1) != 0 || 456267324Semaste write_mappings(fp, VFNT_MAP_BOLD) != 0 || 457267324Semaste write_mappings(fp, 3) != 0) { 458267324Semaste perror(filename); 459267324Semaste return (1); 460267324Semaste } 461219888Sed 462219888Sed return (0); 463219888Sed} 464219888Sed 465267298Semastestatic void 466267298Semasteprint_font_info(void) 467267298Semaste{ 468267298Semaste printf( 469267298Semaste"Statistics:\n" 470267298Semaste"- glyph_total: %5u\n" 471267298Semaste"- glyph_normal: %5u\n" 472267298Semaste"- glyph_normal_right: %5u\n" 473267298Semaste"- glyph_bold: %5u\n" 474267298Semaste"- glyph_bold_right: %5u\n" 475267298Semaste"- glyph_unique: %5u\n" 476267298Semaste"- glyph_dupe: %5u\n" 477267298Semaste"- mapping_total: %5u\n" 478267298Semaste"- mapping_normal: %5u\n" 479267298Semaste"- mapping_normal_folded: %5u\n" 480267298Semaste"- mapping_normal_right: %5u\n" 481267298Semaste"- mapping_normal_right_folded: %5u\n" 482267298Semaste"- mapping_bold: %5u\n" 483267298Semaste"- mapping_bold_folded: %5u\n" 484267298Semaste"- mapping_bold_right: %5u\n" 485267298Semaste"- mapping_bold_right_folded: %5u\n" 486267298Semaste"- mapping_unique: %5u\n" 487267298Semaste"- mapping_dupe: %5u\n", 488267298Semaste glyph_total, 489267298Semaste glyph_count[0], 490267298Semaste glyph_count[1], 491267298Semaste glyph_count[2], 492267298Semaste glyph_count[3], 493267298Semaste glyph_unique, glyph_dupe, 494267298Semaste mapping_total, 495267298Semaste map_count[0], map_folded_count[0], 496267298Semaste map_count[1], map_folded_count[1], 497267298Semaste map_count[2], map_folded_count[2], 498267298Semaste map_count[3], map_folded_count[3], 499267298Semaste mapping_unique, mapping_dupe); 500267298Semaste} 501267298Semaste 502219888Sedint 503219888Sedmain(int argc, char *argv[]) 504219888Sed{ 505267298Semaste int ch, val, verbose = 0; 506219888Sed 507259680Semaste assert(sizeof(struct file_header) == 32); 508219888Sed assert(sizeof(struct file_mapping) == 8); 509219888Sed 510267337Semaste while ((ch = getopt(argc, argv, "h:vw:")) != -1) { 511267011Semaste switch (ch) { 512267011Semaste case 'h': 513267298Semaste val = atoi(optarg); 514267298Semaste if (val <= 0 || val > 128) { 515267298Semaste errx(1, "Invalid height %d", val); 516267298Semaste return (1); 517267298Semaste } 518267298Semaste height = val; 519267011Semaste break; 520267298Semaste case 'v': 521267298Semaste verbose = 1; 522267298Semaste break; 523267011Semaste case 'w': 524267298Semaste val = atoi(optarg); 525267298Semaste if (val <= 0 || val > 128) { 526267298Semaste errx(1, "Invalid width %d", val); 527267298Semaste return (1); 528267298Semaste } 529267298Semaste width = val; 530267011Semaste break; 531267011Semaste case '?': 532267011Semaste default: 533267011Semaste usage(); 534267011Semaste } 535267011Semaste } 536267011Semaste argc -= optind; 537267011Semaste argv += optind; 538267011Semaste 539267012Semaste if (argc < 2 || argc > 3) 540219888Sed usage(); 541267011Semaste 542219888Sed wbytes = howmany(width, 8); 543219888Sed 544267123Semaste if (parse_file(argv[0], VFNT_MAP_NORMAL) != 0) 545219888Sed return (1); 546267012Semaste argc--; 547267012Semaste argv++; 548267012Semaste if (argc == 2) { 549267123Semaste if (parse_file(argv[0], VFNT_MAP_BOLD) != 0) 550267012Semaste return (1); 551267012Semaste argc--; 552267012Semaste argv++; 553267012Semaste } 554219888Sed number_glyphs(); 555267301Semaste dedup_mapping(VFNT_MAP_BOLD); 556267301Semaste dedup_mapping(VFNT_MAP_BOLD_RH); 557219888Sed fold_mappings(0); 558219888Sed fold_mappings(1); 559259680Semaste fold_mappings(2); 560259680Semaste fold_mappings(3); 561267012Semaste if (write_fnt(argv[0]) != 0) 562219888Sed return (1); 563267298Semaste 564267298Semaste if (verbose) 565267298Semaste print_font_info(); 566267298Semaste 567219888Sed return (0); 568219888Sed} 569