151817185Smacallan/* $NetBSD: bdfload.c,v 1.23 2024/03/12 09:42:55 macallan Exp $ */ 2d5f9d0dbSmacallan 3d5f9d0dbSmacallan/* 4d5f9d0dbSmacallan * Copyright (c) 2018 Michael Lorenz 5d5f9d0dbSmacallan * All rights reserved. 6d5f9d0dbSmacallan * 7d5f9d0dbSmacallan * Redistribution and use in source and binary forms, with or without 8d5f9d0dbSmacallan * modification, are permitted provided that the following conditions 9d5f9d0dbSmacallan * are met: 10d5f9d0dbSmacallan * 1. Redistributions of source code must retain the above copyright 11d5f9d0dbSmacallan * notice, this list of conditions and the following disclaimer. 12d5f9d0dbSmacallan * 2. Redistributions in binary form must reproduce the above copyright 13d5f9d0dbSmacallan * notice, this list of conditions and the following disclaimer in the 14d5f9d0dbSmacallan * documentation and/or other materials provided with the distribution. 15d5f9d0dbSmacallan * 16d5f9d0dbSmacallan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17d5f9d0dbSmacallan * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18d5f9d0dbSmacallan * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19d5f9d0dbSmacallan * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20d5f9d0dbSmacallan * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21d5f9d0dbSmacallan * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22d5f9d0dbSmacallan * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23d5f9d0dbSmacallan * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24d5f9d0dbSmacallan * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25d5f9d0dbSmacallan * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26d5f9d0dbSmacallan */ 27d5f9d0dbSmacallan 28d5f9d0dbSmacallan/* 29d5f9d0dbSmacallan * a crude BDF loader for wsdisplay 30d5f9d0dbSmacallan */ 31d5f9d0dbSmacallan 32d5f9d0dbSmacallan#include <stdlib.h> 33d5f9d0dbSmacallan#include <stdio.h> 34d5f9d0dbSmacallan#include <fcntl.h> 35d5f9d0dbSmacallan#include <unistd.h> 36d5f9d0dbSmacallan#include <string.h> 37d5f9d0dbSmacallan#include <errno.h> 38d5f9d0dbSmacallan#include <ctype.h> 39d5f9d0dbSmacallan#include <sys/ioctl.h> 40d5f9d0dbSmacallan#include <err.h> 41d5f9d0dbSmacallan 42d5f9d0dbSmacallan#include <dev/wscons/wsconsio.h> 43d5f9d0dbSmacallan 442b154882Suwe/* 452b154882Suwe * wsdisplay_font but with strings embedded and integer fields in 462b154882Suwe * little endian 472b154882Suwe */ 482b154882Suwestruct wsfthdr { 492b154882Suwe char magic[4]; /* "WSFT" */ 502b154882Suwe char name[64]; 512b154882Suwe uint32_t firstchar; 522b154882Suwe uint32_t numchars; 532b154882Suwe uint32_t encoding; 542b154882Suwe uint32_t fontwidth; 552b154882Suwe uint32_t fontheight; 562b154882Suwe uint32_t stride; 572b154882Suwe uint32_t bitorder; 582b154882Suwe uint32_t byteorder; 592b154882Suwe}; 602b154882Suwe 612b154882Suwe 622b154882Suweconst struct encmap { 632b154882Suwe const char *name; 642b154882Suwe int encoding; 652b154882Suwe} encmap[] = { 662b154882Suwe { "cp437", WSDISPLAY_FONTENC_IBM }, 672b154882Suwe { "ibm", WSDISPLAY_FONTENC_IBM }, 682b154882Suwe { "iso", WSDISPLAY_FONTENC_ISO }, 69a5a7ac3fSmacallan { "iso8859", WSDISPLAY_FONTENC_ISO }, 70a5a7ac3fSmacallan { "iso10646", WSDISPLAY_FONTENC_ISO }, 712b154882Suwe { "iso-8859-1", WSDISPLAY_FONTENC_ISO }, 722b154882Suwe { "iso-8859-2", WSDISPLAY_FONTENC_ISO2 }, 732b154882Suwe { "iso-8859-7", WSDISPLAY_FONTENC_ISO7 }, 742b154882Suwe { "iso2", WSDISPLAY_FONTENC_ISO2 }, 752b154882Suwe { "iso7", WSDISPLAY_FONTENC_ISO7 }, 762b154882Suwe { "iso8859-1", WSDISPLAY_FONTENC_ISO }, 772b154882Suwe { "iso8859-2", WSDISPLAY_FONTENC_ISO2 }, 782b154882Suwe { "iso8859-7", WSDISPLAY_FONTENC_ISO7 }, 792b154882Suwe { "koi8-r", WSDISPLAY_FONTENC_KOI8_R }, 802b154882Suwe { "koi8r", WSDISPLAY_FONTENC_KOI8_R }, 812b154882Suwe { "latin-1", WSDISPLAY_FONTENC_ISO }, 822b154882Suwe { "latin-2", WSDISPLAY_FONTENC_ISO2 }, 832b154882Suwe { "latin1", WSDISPLAY_FONTENC_ISO }, 842b154882Suwe { "latin2", WSDISPLAY_FONTENC_ISO2 }, 852b154882Suwe { "pcvt", WSDISPLAY_FONTENC_PCVT }, 862b154882Suwe { NULL, -1 } 872b154882Suwe}; 882b154882Suwe 892b154882Suweconst char * const encname[] = { 902b154882Suwe#define _ENC(_e) [_e] = #_e 912b154882Suwe _ENC(WSDISPLAY_FONTENC_ISO), 922b154882Suwe _ENC(WSDISPLAY_FONTENC_IBM), 932b154882Suwe _ENC(WSDISPLAY_FONTENC_PCVT), 942b154882Suwe _ENC(WSDISPLAY_FONTENC_ISO7), 952b154882Suwe _ENC(WSDISPLAY_FONTENC_ISO2), 962b154882Suwe _ENC(WSDISPLAY_FONTENC_KOI8_R), 972b154882Suwe}; 982b154882Suwe 992b154882Suwe 1002b154882Suweconst char *ofile = NULL; 1012b154882Suweint encoding = -1; 10261348eb3Smacallanint verbose = 0; 103554a5d78Smacallanint dump = 0; 1042d60533cSmacallanint header = 0; 105a5a7ac3fSmacallanint force = 0; 10653a12b5fSmacallanint scale = 0; 10753a12b5fSmacallanint smoothe = 0; 1087d6aaba4Smacallanchar commentbuf[2048] = ""; 1097d6aaba4Smacallanint commentptr = 0; 11051bbcd86Smacallanchar fontname[64] = ""; 11116ae1398Smacallanchar *names[256]; 1122b154882Suwe 113554a5d78Smacallanvoid 114554a5d78Smacallandump_line(char *gptr, int stride) 115554a5d78Smacallan{ 116554a5d78Smacallan int i, j, msk, c; 117554a5d78Smacallan 118554a5d78Smacallan for (i = 0; i < stride; i++) { 119554a5d78Smacallan c = gptr[i]; 120554a5d78Smacallan msk = 0x80; 121554a5d78Smacallan for (j = 0; j < 8; j++) { 122554a5d78Smacallan putchar((c & msk) != 0 ? '#' : ' '); 123554a5d78Smacallan msk = msk >> 1; 124554a5d78Smacallan } 125554a5d78Smacallan } 126ec211365Smacallan printf("\n"); 127554a5d78Smacallan} 128554a5d78Smacallan 1292d60533cSmacallanvoid 13053a12b5fSmacallanwrite_wsf(const char *oname, struct wsdisplay_font *f) 1312d60533cSmacallan{ 1322d60533cSmacallan struct wsfthdr h; 13353a12b5fSmacallan uint8_t *buffer = f->data; 13453a12b5fSmacallan int buflen = f->numchars * f->stride * f->fontheight; 1352d60533cSmacallan 1362d60533cSmacallan memset(&h, 0, sizeof(h)); 1372d60533cSmacallan strncpy(h.magic, "WSFT", sizeof(h.magic)); 1382d60533cSmacallan strncpy(h.name, f->name, sizeof(h.name)); 1392d60533cSmacallan h.firstchar = htole32(f->firstchar); 1402d60533cSmacallan h.numchars = htole32(f->numchars); 1412d60533cSmacallan h.encoding = htole32(f->encoding); 1422d60533cSmacallan h.fontwidth = htole32(f->fontwidth); 1432d60533cSmacallan h.fontheight = htole32(f->fontheight); 1442d60533cSmacallan h.stride = htole32(f->stride); 1452d60533cSmacallan h.bitorder = htole32(f->bitorder); 1462d60533cSmacallan h.byteorder = htole32(f->byteorder); 1472d60533cSmacallan 1482d60533cSmacallan int wsfd = open(ofile, O_WRONLY | O_CREAT | O_TRUNC, 0644); 1492d60533cSmacallan if (wsfd < 0) 1502d60533cSmacallan err(EXIT_FAILURE, "%s", ofile); 1512d60533cSmacallan 1522d60533cSmacallan ssize_t nwritten; 1532d60533cSmacallan nwritten = write(wsfd, &h, sizeof(h)); 1542d60533cSmacallan if (nwritten < 0) 1552d60533cSmacallan err(EXIT_FAILURE, "%s", ofile); 1562d60533cSmacallan if (nwritten != sizeof(h)) 1572d60533cSmacallan errx(EXIT_FAILURE, "%s: partial write", ofile); 1582d60533cSmacallan 1592d60533cSmacallan nwritten = write(wsfd, buffer, buflen); 1602d60533cSmacallan if (nwritten < 0) 1612d60533cSmacallan err(EXIT_FAILURE, "%s", ofile); 1622d60533cSmacallan if (nwritten != buflen) 1632d60533cSmacallan errx(EXIT_FAILURE, "%s: partial write", ofile); 1642d60533cSmacallan close(wsfd); 1652d60533cSmacallan} 1662d60533cSmacallan 1672d60533cSmacallanint 16853a12b5fSmacallanwrite_header(const char *filename, struct wsdisplay_font *f) 1692d60533cSmacallan{ 1702d60533cSmacallan FILE *output; 171b3baceecSmacallan uint8_t *buffer = f->data; 172b3baceecSmacallan uint8_t c, msk; 1737dd7205fSmacallan int i, j, x, y, idx, pxls, left; 174b3baceecSmacallan char name[64]; 1752d60533cSmacallan 1762d60533cSmacallan /* now output as a header file */ 17743d302b1Smacallan snprintf(name, sizeof(name), "%s_%dx%d", f->name, 1782d60533cSmacallan f->fontwidth, f->fontheight); 17943d302b1Smacallan for (i = 0; i < strlen(name); i++) { 1806c735b96Schristos if (isblank((unsigned char)name[i])) 1816c735b96Schristos name[i] = '_'; 1822d60533cSmacallan } 1832d60533cSmacallan if ((output = fopen(filename, "w")) == NULL) { 1846c735b96Schristos warn("Can't open output file `%s'", filename); 1852d60533cSmacallan return -1; 1862d60533cSmacallan } 1877d6aaba4Smacallan if (commentptr > 0) { 1887d6aaba4Smacallan fprintf(output, "/*\n"); 1897d6aaba4Smacallan fputs(commentbuf, output); 1907d6aaba4Smacallan fprintf(output, "*/\n\n"); 1917d6aaba4Smacallan } 1927d6aaba4Smacallan 19343d302b1Smacallan fprintf(output, "static u_char %s_data[];\n", name); 1942d60533cSmacallan fprintf(output, "\n"); 19543d302b1Smacallan fprintf(output, "static struct wsdisplay_font %s = {\n", name); 19651bbcd86Smacallan fprintf(output, "\t\"%s\",\t\t\t/* typeface name */\n", f->name); 1972d60533cSmacallan fprintf(output, "\t%d,\t\t\t\t/* firstchar */\n", f->firstchar); 1982d60533cSmacallan fprintf(output, "\t%d,\t\t\t\t/* numchars */\n", f->numchars); 1992d60533cSmacallan fprintf(output, "\t%d,\t\t\t\t/* encoding */\n", f->encoding); 2002d60533cSmacallan fprintf(output, "\t%d,\t\t\t\t/* fontwidth */\n", f->fontwidth); 2012d60533cSmacallan fprintf(output, "\t%d,\t\t\t\t/* fontheight */\n", f->fontheight); 2022d60533cSmacallan fprintf(output, "\t%d,\t\t\t\t/* stride */\n", f->stride); 2032d60533cSmacallan fprintf(output, "\tWSDISPLAY_FONTORDER_L2R,\t/* bit order */\n"); 2042d60533cSmacallan fprintf(output, "\tWSDISPLAY_FONTORDER_L2R,\t/* byte order */\n"); 20543d302b1Smacallan fprintf(output, "\t%s_data\t\t/* data */\n", name); 2062d60533cSmacallan fprintf(output, "};\n\n"); 20743d302b1Smacallan fprintf(output, "static u_char %s_data[] = {\n", name); 20853a12b5fSmacallan for (i = 0; i < f->numchars; i++) { 20916ae1398Smacallan if (names[i] != NULL) { 21053a12b5fSmacallan fprintf(output, "\t/* %d %s */\n", i + f->firstchar, names[i]); 21116ae1398Smacallan } else 21253a12b5fSmacallan fprintf(output, "\t/* %d */\n", i + f->firstchar); 2132d60533cSmacallan idx = i * f->stride * f->fontheight; 2142d60533cSmacallan for (y = 0; y < f->fontheight; y++) { 2152d60533cSmacallan for (x = 0; x < f->stride; x++) { 2162d60533cSmacallan fprintf(output, "0x%02x, ",buffer[idx + x]); 2172d60533cSmacallan } 2182d60533cSmacallan fprintf(output, "/* "); 2197dd7205fSmacallan pxls = f->fontwidth; 2202d60533cSmacallan for (x = 0; x < f->stride; x++) { 2212d60533cSmacallan c = buffer[idx + x]; 2222d60533cSmacallan msk = 0x80; 2237dd7205fSmacallan left = pxls > 8 ? 8 : pxls; 2247dd7205fSmacallan for (j = 0; j < left; j++) { 225426ebb7fSmacallan fprintf(output, "%s", 226426ebb7fSmacallan (c & msk) != 0 ? "[]" : ". "); 2272d60533cSmacallan msk = msk >> 1; 2282d60533cSmacallan } 2297dd7205fSmacallan pxls -= 8; 2302d60533cSmacallan } 2312d60533cSmacallan fprintf(output, " */\n"); 2322d60533cSmacallan 2332d60533cSmacallan idx += f->stride; 2342d60533cSmacallan } 2352d60533cSmacallan } 2362d60533cSmacallan fprintf(output, "};\n"); 2372d60533cSmacallan fclose(output); 2382d60533cSmacallan return 0; 2392d60533cSmacallan} 2402d60533cSmacallan 24153a12b5fSmacallanvoid 24253a12b5fSmacallandouble_pixels(uint8_t *inbuf, uint16_t *outbuf, int bytes) 24353a12b5fSmacallan{ 24453a12b5fSmacallan int i, j; 24553a12b5fSmacallan uint16_t outmask, out; 24653a12b5fSmacallan uint8_t in, inmask; 24753a12b5fSmacallan 24853a12b5fSmacallan for (i = 0; i < bytes; i++) { 24953a12b5fSmacallan inmask = 0x80; 25053a12b5fSmacallan outmask = 0xc000; 25153a12b5fSmacallan out = 0; 25253a12b5fSmacallan in = inbuf[i]; 25353a12b5fSmacallan for (j = 0; j < 8; j++) { 25453a12b5fSmacallan if (in & inmask) { 25553a12b5fSmacallan out |= outmask; 25653a12b5fSmacallan } 25753a12b5fSmacallan inmask = inmask >> 1; 25853a12b5fSmacallan outmask = outmask >> 2; 25953a12b5fSmacallan } 26053a12b5fSmacallan outbuf[i * 2] = htobe16(out); 26153a12b5fSmacallan } 26253a12b5fSmacallan} 26353a12b5fSmacallan 26453a12b5fSmacallanvoid fill_dup(uint16_t *buf, int lines) 26553a12b5fSmacallan{ 26653a12b5fSmacallan int i; 26753a12b5fSmacallan for (i = 0; i < lines; i++) { 26853a12b5fSmacallan buf[2 * i + 1] = buf[2 * i]; 26953a12b5fSmacallan } 27053a12b5fSmacallan} 27153a12b5fSmacallan 27253a12b5fSmacallanvoid smoothe_pixels(uint16_t *buf, int lines) 27353a12b5fSmacallan{ 27453a12b5fSmacallan int i, j, topright, topleft, botright, botleft; 27553a12b5fSmacallan uint16_t pmask, in, prev, next, out; 27653a12b5fSmacallan for (i = 0; i < lines; i++) { 27753a12b5fSmacallan pmask = 0xc000; 27853a12b5fSmacallan in = be16toh(buf[i]); 27953a12b5fSmacallan out = in; 28053a12b5fSmacallan prev = next = 0; 28153a12b5fSmacallan if (i > 1) prev = be16toh(buf[i - 2]); 28253a12b5fSmacallan if (i < (lines - 2)) next = be16toh(buf[i + 2]); 28353a12b5fSmacallan for (j = 0; j < 8; j++) { 28453a12b5fSmacallan if ((in & pmask) == 0) { 28553a12b5fSmacallan /* empty pixel, check surroundings */ 28653a12b5fSmacallan topright = topleft = botright = botleft = 0; 28753a12b5fSmacallan if (((i & 1) == 0) && (j < 6)) 28853a12b5fSmacallan topright = (((prev & pmask) == pmask) && 28953a12b5fSmacallan ((prev & (pmask >> 2)) != 0) && 29053a12b5fSmacallan ((in & (pmask >> 2)) != 0)); 29153a12b5fSmacallan if (((i & 1) == 0) && (j > 0)) 29253a12b5fSmacallan topleft = (((prev & pmask) == pmask) && 29353a12b5fSmacallan ((prev & (pmask << 2)) != 0) && 29453a12b5fSmacallan ((in & (pmask << 2)) != 0)); 29553a12b5fSmacallan if ((i & 1) && (j < 6)) 29653a12b5fSmacallan botright = (((next & pmask) == pmask) && 29753a12b5fSmacallan ((next & (pmask >> 2)) != 0) && 29853a12b5fSmacallan ((in & (pmask >> 2)) != 0)); 29953a12b5fSmacallan if ((i & 1) && (j > 0)) 30053a12b5fSmacallan botleft = (((next & pmask) == pmask) && 30153a12b5fSmacallan ((next & (pmask << 2)) != 0) && 30253a12b5fSmacallan ((in & (pmask << 2)) != 0)); 30353a12b5fSmacallan if ((topright + topleft + botright + botleft) == 1) { 30453a12b5fSmacallan if (topleft || botleft) out |= pmask << 1; 30553a12b5fSmacallan if (topright || botright) out |= pmask >> 1; 30653a12b5fSmacallan } 30753a12b5fSmacallan } 30853a12b5fSmacallan pmask = pmask >> 2; 30953a12b5fSmacallan } 31053a12b5fSmacallan buf[i] = htobe16(out); 31153a12b5fSmacallan } 31253a12b5fSmacallan} 31353a12b5fSmacallan 314d5f9d0dbSmacallanvoid 315d5f9d0dbSmacallaninterpret(FILE *foo) 316d5f9d0dbSmacallan{ 317999c8572Smacallan char line[128], *arg, name[64] = "foo", *buffer, *cbitmap; 31816ae1398Smacallan char charname[65], *charnamebuf; 31916ae1398Smacallan int buflen = -1, charnamebufptr = 0, j; 3206c735b96Schristos int in_char = 0, current = -1, stride = 0, charsize = 0; 321d5f9d0dbSmacallan int width, height, x, y, num; 322d5f9d0dbSmacallan int first = 255, last = 0; 323d5f9d0dbSmacallan int left, top, lines; 324d5f9d0dbSmacallan int bl = 255, bt = 255, br = -1, bb = -1; 325d5f9d0dbSmacallan struct wsdisplay_font f; 3262b154882Suwe int status; 327d5f9d0dbSmacallan 32816ae1398Smacallan charnamebuf = malloc(64 * 256); 32916ae1398Smacallan if (charnamebuf == 0) err(EXIT_FAILURE, "failed to allocate memory\n"); 33016ae1398Smacallan memset(charnamebuf, 0, 64 * 256); 33116ae1398Smacallan for (j = 0; j < 256; j++) names[j] = NULL; 33216ae1398Smacallan 333d5f9d0dbSmacallan while (fgets(line, sizeof(line), foo) != NULL) { 3346c735b96Schristos size_t i = 0, len; 335d5f9d0dbSmacallan /* separate keyword from parameters */ 336d5f9d0dbSmacallan len = strlen(line); 3376c735b96Schristos while (!isspace((unsigned char)line[i]) && i < len) i++; 338d5f9d0dbSmacallan line[i] = 0; 339d5f9d0dbSmacallan arg = &line[i + 1]; 340d5f9d0dbSmacallan i = 0; 341d5f9d0dbSmacallan len = strlen(arg); 342d5f9d0dbSmacallan /* get rid of garbage */ 3436c735b96Schristos while ((!iscntrl((unsigned char)arg[i])) && (arg[i] != 0)) { 344d5f9d0dbSmacallan i++; 345d5f9d0dbSmacallan } 346d5f9d0dbSmacallan arg[i] = 0; 347d5f9d0dbSmacallan if (strcmp(line, "FAMILY_NAME") == 0) { 348682eda17Smacallan char *q; 349d5f9d0dbSmacallan /* cut off quotation marks */ 3506c735b96Schristos strlcpy(name, arg + 1, 64); 351682eda17Smacallan /* remove trailing " */ 352682eda17Smacallan if ((q = strnstr(name, "\"", 64)) != NULL) 353682eda17Smacallan *q = 0; 35461348eb3Smacallan if (verbose) printf("name: %s\n", name); 3557d6aaba4Smacallan } else if (strcmp(line, "COMMENT") == 0) { 3567d6aaba4Smacallan commentptr += snprintf(&commentbuf[commentptr], 3576c735b96Schristos sizeof(commentbuf) - commentptr, "%s\n", arg); 358a5a7ac3fSmacallan } else if (strcmp(line, "SPACING") == 0) { 359a5a7ac3fSmacallan char spc[16]; 360a5a7ac3fSmacallan int res; 361a5a7ac3fSmacallan res = sscanf(arg, "%s", spc); 362a5a7ac3fSmacallan if (res > 0) { 363a5a7ac3fSmacallan if (verbose) printf("spacing %s\n", spc); 364a5a7ac3fSmacallan if ((spc[1] == 'P') && (force == 0)) { 3656c735b96Schristos warnx("This is a proportional font, " 3666c735b96Schristos "results are probably not suitable " 3676c735b96Schristos "for console use."); 3686c735b96Schristos errx(EXIT_FAILURE, "Use -f to override " 3696c735b96Schristos "if you want to try it anyway."); 370a5a7ac3fSmacallan } 371a5a7ac3fSmacallan } 372d5f9d0dbSmacallan } else if (strcmp(line, "FONTBOUNDINGBOX") == 0) { 373d5f9d0dbSmacallan int res; 374d5f9d0dbSmacallan res = sscanf(arg, "%d %d %d %d", 375d5f9d0dbSmacallan &width, &height, &x, &y); 376d5f9d0dbSmacallan stride = (width + 7) >> 3; 37761348eb3Smacallan if (verbose) printf("box %d x %d\n", width, height); 378d5f9d0dbSmacallan if (stride > 2) { 3796c735b96Schristos errx(EXIT_FAILURE, 38061348eb3Smacallan "no fonts wider than 16 work for now\n"); 381d5f9d0dbSmacallan } 382d5f9d0dbSmacallan charsize = height * stride; 383999c8572Smacallan buflen = 257 * charsize; 3842b154882Suwe buffer = calloc(1, buflen); 385d5f9d0dbSmacallan if (buffer == NULL) { 38661348eb3Smacallan err(EXIT_FAILURE, 38761348eb3Smacallan "failed to allocate %dKB for glyphs\n", 388d5f9d0dbSmacallan buflen); 389ce18d260Suwe } 390999c8572Smacallan cbitmap = buffer + 256 * charsize; 391d5f9d0dbSmacallan } else if (strcmp(line, "CHARS") == 0) { 392d5f9d0dbSmacallan if (sscanf(arg, "%d", &num) == 1) 39361348eb3Smacallan if (verbose) 39461348eb3Smacallan printf("number of characters: %d\n", num); 395d5f9d0dbSmacallan } else if (strcmp(line, "STARTCHAR") == 0) { 396d5f9d0dbSmacallan in_char = 1; 397999c8572Smacallan if (charsize <= 1) err(EXIT_FAILURE, 398999c8572Smacallan "syntax error - no valid FONTBOUNDINGBOX\n"); 399999c8572Smacallan memset(cbitmap, 0, charsize); 40016ae1398Smacallan strlcpy(charname, arg, 64); 4014ffa922fSmacallan if (dump && (strlen(charname) > 0)) 4024ffa922fSmacallan printf("name: %s\n", charname); 4034ffa922fSmacallan 404d5f9d0dbSmacallan } else if (strcmp(line, "ENDCHAR") == 0) { 405d5f9d0dbSmacallan in_char = 0; 406999c8572Smacallan /* only commit the glyph if it's in range */ 407999c8572Smacallan if ((current >= 0) && (current < 256)) { 408999c8572Smacallan memcpy(&buffer[charsize * current], 409999c8572Smacallan cbitmap, charsize); 41016ae1398Smacallan if ((strlen(charname) > 0) && 41116ae1398Smacallan (charnamebufptr < 255 * 64)) { 41216ae1398Smacallan char *cur; 41316ae1398Smacallan int len; 41416ae1398Smacallan /* copy name into buffer, keep a 41516ae1398Smacallan * pointer to it for later */ 41616ae1398Smacallan cur = &charnamebuf[charnamebufptr]; 41716ae1398Smacallan len = strlcpy(cur, charname, 64); 41816ae1398Smacallan charnamebufptr += len + 1; 41916ae1398Smacallan names[current] = cur; 42016ae1398Smacallan } 421999c8572Smacallan } 422d5f9d0dbSmacallan current = -1; 423d5f9d0dbSmacallan } else if (strcmp(line, "ENCODING") == 0) { 424d5f9d0dbSmacallan if (sscanf(arg, "%d", ¤t) == 1) { 425d5f9d0dbSmacallan if (current >= 0 && current < 256) { 426d5f9d0dbSmacallan if (current < first) first = current; 427d5f9d0dbSmacallan if (current > last) last = current; 428554a5d78Smacallan if (dump) printf("glyph %d\n", current); 429d5f9d0dbSmacallan } 430d5f9d0dbSmacallan } 431d5f9d0dbSmacallan } else if (strcmp(line, "BBX") == 0) { 432d5f9d0dbSmacallan int cx, cy, cwi, che; 433d5f9d0dbSmacallan if (sscanf(arg, "%d %d %d %d", &cwi, &che, &cx, &cy) 434d5f9d0dbSmacallan == 4) { 435d5f9d0dbSmacallan left = cx; 436d5f9d0dbSmacallan lines = che; 437d5f9d0dbSmacallan top = height + y - che - cy; 438d5f9d0dbSmacallan if (left < bl) bl = left; 439d5f9d0dbSmacallan if (top < bt) bt = top; 440d5f9d0dbSmacallan if ((left + cwi) > br) br = left + cwi; 441d5f9d0dbSmacallan if ((top + che) > bb) bb = top + che; 4426c735b96Schristos if (dump && verbose) 4436c735b96Schristos printf("top %d left %d\n", top, left); 444d5f9d0dbSmacallan } 445d5f9d0dbSmacallan } else if (strcmp(line, "BITMAP") == 0) { 446d5f9d0dbSmacallan int i, j, k, l; 447d5f9d0dbSmacallan char num[32]; 448999c8572Smacallan char *gptr = cbitmap; 449d5f9d0dbSmacallan char *bptr = gptr + top; 450d5f9d0dbSmacallan uint16_t *bptr16 = (uint16_t *)gptr; 451d5f9d0dbSmacallan bptr16 += top; 452d5f9d0dbSmacallan /* see if the character is in range */ 453d5f9d0dbSmacallan if ((current < 0) || (current > 255)) continue; 454d5f9d0dbSmacallan /* now we read & render the character */ 455d5f9d0dbSmacallan for (i = 0; i < lines; i++) { 456d5f9d0dbSmacallan fgets(num, 32, foo); 457d5f9d0dbSmacallan sscanf(num, "%x", &l); 458d5f9d0dbSmacallan if ((stride) == 2 && (strlen(num) < 4)) 459d5f9d0dbSmacallan l = l << 8; 460d5f9d0dbSmacallan l = l >> left; 461d5f9d0dbSmacallan if (stride == 1) { 462b9e0dc8cSmacallan *bptr = l; 463b9e0dc8cSmacallan bptr++; 464d5f9d0dbSmacallan } else { 465d5f9d0dbSmacallan *bptr16 = htobe16(l); 466d5f9d0dbSmacallan bptr16++; 467ce18d260Suwe } 468d5f9d0dbSmacallan } 469554a5d78Smacallan if (dump) { 470999c8572Smacallan gptr = cbitmap; 471554a5d78Smacallan for (i = 0; i < height; i++) { 472554a5d78Smacallan dump_line(gptr, stride); 473554a5d78Smacallan gptr += stride; 474554a5d78Smacallan } 475554a5d78Smacallan } 476d5f9d0dbSmacallan } 477d5f9d0dbSmacallan } 47861348eb3Smacallan if (verbose) { 47961348eb3Smacallan printf("range %d to %d\n", first, last); 48061348eb3Smacallan printf("encoding: %s\n", encname[encoding]); 48161348eb3Smacallan printf("actual box: %d %d %d %d\n", bl, bt, br, bb); 48261348eb3Smacallan } 4832b154882Suwe 484d5f9d0dbSmacallan /* now stuff it into a something wsfont understands */ 485d5f9d0dbSmacallan f.firstchar = first; 4862b154882Suwe f.numchars = last - first + 1; 4872b154882Suwe f.encoding = encoding; 48851bbcd86Smacallan if (fontname[0] == 0) { 48951bbcd86Smacallan f.name = name; 49051bbcd86Smacallan } else f.name = fontname; 491d5f9d0dbSmacallan f.bitorder = WSDISPLAY_FONTORDER_L2R; 492d5f9d0dbSmacallan f.byteorder = WSDISPLAY_FONTORDER_L2R; 49353a12b5fSmacallan 49453a12b5fSmacallan if (scale) { 49553a12b5fSmacallan uint16_t *outbuf; 49653a12b5fSmacallan uint8_t *inbuf; 49753a12b5fSmacallan int i; 49853a12b5fSmacallan 49953a12b5fSmacallan if (stride != 1) err(EXIT_FAILURE, 50053a12b5fSmacallan "scaling works only on fonts up to 8 pixels wide\n"); 50153a12b5fSmacallan f.fontwidth = width * 2 /*(width + 3) & ~3*/; 50253a12b5fSmacallan f.fontheight = height * 2; 50353a12b5fSmacallan f.stride = stride * 2; 50453a12b5fSmacallan outbuf = calloc(1, f.numchars * charsize * 4); 50553a12b5fSmacallan if (outbuf == NULL) err(EXIT_FAILURE, 50653a12b5fSmacallan "failed to allocete memory for scale buffer\n"); 50753a12b5fSmacallan f.data = outbuf; 50853a12b5fSmacallan inbuf = &buffer[first * charsize]; 50953a12b5fSmacallan for (i = 0; i < f.numchars; i++) { 51053a12b5fSmacallan double_pixels(inbuf, outbuf, charsize); 51153a12b5fSmacallan fill_dup(outbuf, charsize); 51253a12b5fSmacallan if (smoothe) smoothe_pixels(outbuf, charsize * 2); 51353a12b5fSmacallan inbuf += charsize; 51453a12b5fSmacallan outbuf += charsize * 2; 51553a12b5fSmacallan } 51653a12b5fSmacallan 51753a12b5fSmacallan } else { 51853a12b5fSmacallan f.fontwidth = width /*(width + 3) & ~3*/; 51953a12b5fSmacallan f.fontheight = height; 52053a12b5fSmacallan f.stride = stride; 52153a12b5fSmacallan f.data = &buffer[first * charsize]; 52253a12b5fSmacallan } 523d5f9d0dbSmacallan 5242b154882Suwe if (ofile == NULL) { 5252b154882Suwe int fdev = open("/dev/wsfont", O_RDWR, 0); 5262b154882Suwe if (fdev < 0) 5272b154882Suwe err(EXIT_FAILURE, "/dev/wsfont"); 5282b154882Suwe status = ioctl(fdev, WSDISPLAYIO_LDFONT, &f); 5292b154882Suwe if (status != 0) 5302b154882Suwe err(EXIT_FAILURE, "WSDISPLAYIO_LDFONT"); 5312b154882Suwe close(fdev); 5322b154882Suwe } 5332b154882Suwe else { 5346c735b96Schristos if (header == 0) 53553a12b5fSmacallan write_wsf(ofile, &f); 5366c735b96Schristos else 53753a12b5fSmacallan write_header(ofile, &f); 5382b154882Suwe } 539d5f9d0dbSmacallan} 540d5f9d0dbSmacallan 5412b154882Suwe__dead void 5422b154882Suweusage() 5432b154882Suwe{ 54453a12b5fSmacallan fprintf(stderr, "Usage: %s [-vdhf2s] [-e encoding] [-N name] " 5456c735b96Schristos "[-o ofile.wsf] font.bdf\n", getprogname()); 5462b154882Suwe exit(EXIT_FAILURE); 5472b154882Suwe} 5482b154882Suwe 5492b154882Suweint 550d5f9d0dbSmacallanmain(int argc, char *argv[]) 551d5f9d0dbSmacallan{ 552d5f9d0dbSmacallan FILE *foo; 5532b154882Suwe const char *encname = NULL; 5542b154882Suwe 5552b154882Suwe int c; 55653a12b5fSmacallan while ((c = getopt(argc, argv, "e:o:N:vdhf2s")) != -1) { 5572b154882Suwe switch (c) { 5582b154882Suwe 5592b154882Suwe /* font encoding */ 5602b154882Suwe case 'e': 5612b154882Suwe if (encname != NULL) 5622b154882Suwe usage(); 5632b154882Suwe encname = optarg; 5642b154882Suwe break; 5652b154882Suwe 5662b154882Suwe /* output file name */ 5672b154882Suwe case 'o': 5682b154882Suwe if (ofile != NULL) 5692b154882Suwe usage(); 5702b154882Suwe ofile = optarg; 5712b154882Suwe break; 5722b154882Suwe 57361348eb3Smacallan case 'v': 57461348eb3Smacallan verbose = 1; 57561348eb3Smacallan break; 57661348eb3Smacallan 577554a5d78Smacallan case 'd': 578554a5d78Smacallan dump = 1; 579554a5d78Smacallan break; 580554a5d78Smacallan 5812d60533cSmacallan case 'h': 5822d60533cSmacallan header = 1; 5832d60533cSmacallan break; 584a5a7ac3fSmacallan case 'f': 585a5a7ac3fSmacallan force = 1; 586a5a7ac3fSmacallan break; 58753a12b5fSmacallan case '2': 58853a12b5fSmacallan scale = 1; 58953a12b5fSmacallan break; 59053a12b5fSmacallan case 's': 59153a12b5fSmacallan smoothe = 1; 59253a12b5fSmacallan break; 59351bbcd86Smacallan case 'N': 59451bbcd86Smacallan strncpy(fontname, optarg, 64); 59551bbcd86Smacallan break; 5962b154882Suwe case '?': /* FALLTHROUGH */ 5972b154882Suwe default: 5982b154882Suwe usage(); 599d5f9d0dbSmacallan } 600d5f9d0dbSmacallan } 6012b154882Suwe 6022b154882Suwe argc -= optind; 6032b154882Suwe argv += optind; 6042b154882Suwe 6052b154882Suwe if (encname == NULL) { 6062b154882Suwe encoding = WSDISPLAY_FONTENC_ISO; 6072b154882Suwe } 6082b154882Suwe else { 6092b154882Suwe for (const struct encmap *e = encmap; e->name; ++e) { 6102b154882Suwe if (strcmp(e->name, encname) == 0) { 6112b154882Suwe encoding = e->encoding; 6122b154882Suwe break; 6132b154882Suwe } 6142b154882Suwe } 6152b154882Suwe } 6162b154882Suwe 6172b154882Suwe /* get encoding from the bdf file? */ 6182b154882Suwe if (encoding == -1) 6192b154882Suwe encoding = WSDISPLAY_FONTENC_ISO; 6202b154882Suwe 6212b154882Suwe if (argc == 0) 6222b154882Suwe usage(); 6232b154882Suwe 6242b154882Suwe const char *bdfname = argv[0]; 6252b154882Suwe foo = fopen(bdfname, "r"); 6262b154882Suwe if (foo == NULL) 6272b154882Suwe err(EXIT_FAILURE, "%s", bdfname); 6282b154882Suwe 6292b154882Suwe interpret(foo); 6302b154882Suwe return EXIT_SUCCESS; 631d5f9d0dbSmacallan} 632