bdfload.c revision 2b154882
12b154882Suwe/* $NetBSD: bdfload.c,v 1.3 2022/06/08 19:19:42 uwe 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 }, 692b154882Suwe { "iso-8859-1", WSDISPLAY_FONTENC_ISO }, 702b154882Suwe { "iso-8859-2", WSDISPLAY_FONTENC_ISO2 }, 712b154882Suwe { "iso-8859-7", WSDISPLAY_FONTENC_ISO7 }, 722b154882Suwe { "iso2", WSDISPLAY_FONTENC_ISO2 }, 732b154882Suwe { "iso7", WSDISPLAY_FONTENC_ISO7 }, 742b154882Suwe { "iso8859-1", WSDISPLAY_FONTENC_ISO }, 752b154882Suwe { "iso8859-2", WSDISPLAY_FONTENC_ISO2 }, 762b154882Suwe { "iso8859-7", WSDISPLAY_FONTENC_ISO7 }, 772b154882Suwe { "koi8-r", WSDISPLAY_FONTENC_KOI8_R }, 782b154882Suwe { "koi8r", WSDISPLAY_FONTENC_KOI8_R }, 792b154882Suwe { "latin-1", WSDISPLAY_FONTENC_ISO }, 802b154882Suwe { "latin-2", WSDISPLAY_FONTENC_ISO2 }, 812b154882Suwe { "latin1", WSDISPLAY_FONTENC_ISO }, 822b154882Suwe { "latin2", WSDISPLAY_FONTENC_ISO2 }, 832b154882Suwe { "pcvt", WSDISPLAY_FONTENC_PCVT }, 842b154882Suwe { NULL, -1 } 852b154882Suwe}; 862b154882Suwe 872b154882Suweconst char * const encname[] = { 882b154882Suwe#define _ENC(_e) [_e] = #_e 892b154882Suwe _ENC(WSDISPLAY_FONTENC_ISO), 902b154882Suwe _ENC(WSDISPLAY_FONTENC_IBM), 912b154882Suwe _ENC(WSDISPLAY_FONTENC_PCVT), 922b154882Suwe _ENC(WSDISPLAY_FONTENC_ISO7), 932b154882Suwe _ENC(WSDISPLAY_FONTENC_ISO2), 942b154882Suwe _ENC(WSDISPLAY_FONTENC_KOI8_R), 952b154882Suwe}; 962b154882Suwe 972b154882Suwe 982b154882Suweconst char *ofile = NULL; 992b154882Suweint encoding = -1; 1002b154882Suwe 1012b154882Suwe 102d5f9d0dbSmacallanvoid 103d5f9d0dbSmacallaninterpret(FILE *foo) 104d5f9d0dbSmacallan{ 1052b154882Suwe char line[128], *arg, name[64] = "foop", *buffer; 1062b154882Suwe int buflen = -1; 107d5f9d0dbSmacallan int len, in_char = 0, current = -1, stride = 0, charsize = 0; 108d5f9d0dbSmacallan int width, height, x, y, num; 109d5f9d0dbSmacallan int first = 255, last = 0; 110d5f9d0dbSmacallan int left, top, lines; 111d5f9d0dbSmacallan int bl = 255, bt = 255, br = -1, bb = -1; 112d5f9d0dbSmacallan struct wsdisplay_font f; 1132b154882Suwe int status; 114d5f9d0dbSmacallan 115d5f9d0dbSmacallan while (fgets(line, sizeof(line), foo) != NULL) { 116d5f9d0dbSmacallan int i = 0; 117d5f9d0dbSmacallan /* separate keyword from parameters */ 118d5f9d0dbSmacallan len = strlen(line); 119d5f9d0dbSmacallan while (!isspace(line[i]) && (i < len)) i++; 120d5f9d0dbSmacallan line[i] = 0; 121d5f9d0dbSmacallan arg = &line[i + 1]; 122d5f9d0dbSmacallan i = 0; 123d5f9d0dbSmacallan len = strlen(arg); 124d5f9d0dbSmacallan /* get rid of garbage */ 125d5f9d0dbSmacallan while ((!iscntrl(arg[i])) && (arg[i] != 0)) { 126d5f9d0dbSmacallan i++; 127d5f9d0dbSmacallan } 128d5f9d0dbSmacallan arg[i] = 0; 129d5f9d0dbSmacallan if (strcmp(line, "FAMILY_NAME") == 0) { 130d5f9d0dbSmacallan /* cut off quotation marks */ 131d5f9d0dbSmacallan strncpy(name, arg + 1, 64); 132d5f9d0dbSmacallan name[strlen(name) - 1] = 0; 133d5f9d0dbSmacallan printf("name: %s\n", name); 134d5f9d0dbSmacallan } else if (strcmp(line, "FONTBOUNDINGBOX") == 0) { 135d5f9d0dbSmacallan int res; 136d5f9d0dbSmacallan res = sscanf(arg, "%d %d %d %d", 137d5f9d0dbSmacallan &width, &height, &x, &y); 138d5f9d0dbSmacallan stride = (width + 7) >> 3; 139d5f9d0dbSmacallan printf("box %d x %d\n", width, height); 140d5f9d0dbSmacallan if (stride > 2) { 141d5f9d0dbSmacallan printf("no fonts wider than 16 work for now\n"); 142d5f9d0dbSmacallan exit(1); 143d5f9d0dbSmacallan } 144d5f9d0dbSmacallan charsize = height * stride; 145d5f9d0dbSmacallan buflen = 256 * charsize; 1462b154882Suwe buffer = calloc(1, buflen); 147d5f9d0dbSmacallan if (buffer == NULL) { 148d5f9d0dbSmacallan printf("failed to allocate %dKB for glyphs\n", 149d5f9d0dbSmacallan buflen); 150d5f9d0dbSmacallan exit(1); 151ce18d260Suwe } 152d5f9d0dbSmacallan } else if (strcmp(line, "CHARS") == 0) { 153d5f9d0dbSmacallan if (sscanf(arg, "%d", &num) == 1) 154d5f9d0dbSmacallan printf("number of characters: %d\n", num); 155d5f9d0dbSmacallan } else if (strcmp(line, "STARTCHAR") == 0) { 156d5f9d0dbSmacallan in_char = 1; 157d5f9d0dbSmacallan } else if (strcmp(line, "ENDCHAR") == 0) { 158d5f9d0dbSmacallan in_char = 0; 159d5f9d0dbSmacallan current = -1; 160d5f9d0dbSmacallan } else if (strcmp(line, "ENCODING") == 0) { 161d5f9d0dbSmacallan if (sscanf(arg, "%d", ¤t) == 1) { 162d5f9d0dbSmacallan if (current >= 0 && current < 256) { 163d5f9d0dbSmacallan if (current < first) first = current; 164d5f9d0dbSmacallan if (current > last) last = current; 165d5f9d0dbSmacallan } 166d5f9d0dbSmacallan } 167d5f9d0dbSmacallan } else if (strcmp(line, "BBX") == 0) { 168d5f9d0dbSmacallan int cx, cy, cwi, che; 169d5f9d0dbSmacallan if (sscanf(arg, "%d %d %d %d", &cwi, &che, &cx, &cy) 170d5f9d0dbSmacallan == 4) { 171d5f9d0dbSmacallan left = cx; 172d5f9d0dbSmacallan lines = che; 173d5f9d0dbSmacallan top = height + y - che - cy; 174d5f9d0dbSmacallan if (left < bl) bl = left; 175d5f9d0dbSmacallan if (top < bt) bt = top; 176d5f9d0dbSmacallan if ((left + cwi) > br) br = left + cwi; 177d5f9d0dbSmacallan if ((top + che) > bb) bb = top + che; 178d5f9d0dbSmacallan } 179d5f9d0dbSmacallan } else if (strcmp(line, "BITMAP") == 0) { 180d5f9d0dbSmacallan int i, j, k, l; 181d5f9d0dbSmacallan char num[32]; 182d5f9d0dbSmacallan char *gptr = &buffer[charsize * current]; 183d5f9d0dbSmacallan char *bptr = gptr + top; 184d5f9d0dbSmacallan uint16_t *bptr16 = (uint16_t *)gptr; 185d5f9d0dbSmacallan bptr16 += top; 186d5f9d0dbSmacallan /* see if the character is in range */ 187d5f9d0dbSmacallan if ((current < 0) || (current > 255)) continue; 188d5f9d0dbSmacallan /* now we read & render the character */ 189d5f9d0dbSmacallan for (i = 0; i < lines; i++) { 190d5f9d0dbSmacallan fgets(num, 32, foo); 191d5f9d0dbSmacallan sscanf(num, "%x", &l); 192d5f9d0dbSmacallan if ((stride) == 2 && (strlen(num) < 4)) 193d5f9d0dbSmacallan l = l << 8; 194d5f9d0dbSmacallan l = l >> left; 195d5f9d0dbSmacallan if (stride == 1) { 196d5f9d0dbSmacallan *gptr = l; 197d5f9d0dbSmacallan gptr++; 198d5f9d0dbSmacallan } else { 199d5f9d0dbSmacallan *bptr16 = htobe16(l); 200d5f9d0dbSmacallan bptr16++; 201ce18d260Suwe } 202d5f9d0dbSmacallan } 203d5f9d0dbSmacallan } 204d5f9d0dbSmacallan } 205d5f9d0dbSmacallan printf("range %d to %d\n", first, last); 2062b154882Suwe printf("encoding: %s\n", encname[encoding]); 207d5f9d0dbSmacallan printf("actual box: %d %d %d %d\n", bl, bt, br, bb); 2082b154882Suwe 209d5f9d0dbSmacallan /* now stuff it into a something wsfont understands */ 210d5f9d0dbSmacallan f.fontwidth = width /*(width + 3) & ~3*/; 211d5f9d0dbSmacallan f.fontheight = height; 212d5f9d0dbSmacallan f.firstchar = first; 2132b154882Suwe f.numchars = last - first + 1; 214d5f9d0dbSmacallan f.stride = stride; 2152b154882Suwe f.encoding = encoding; 216d5f9d0dbSmacallan f.name = name; 217d5f9d0dbSmacallan f.bitorder = WSDISPLAY_FONTORDER_L2R; 218d5f9d0dbSmacallan f.byteorder = WSDISPLAY_FONTORDER_L2R; 219d5f9d0dbSmacallan f.data = &buffer[first * charsize]; 220d5f9d0dbSmacallan 2212b154882Suwe if (ofile == NULL) { 2222b154882Suwe int fdev = open("/dev/wsfont", O_RDWR, 0); 2232b154882Suwe if (fdev < 0) 2242b154882Suwe err(EXIT_FAILURE, "/dev/wsfont"); 2252b154882Suwe status = ioctl(fdev, WSDISPLAYIO_LDFONT, &f); 2262b154882Suwe if (status != 0) 2272b154882Suwe err(EXIT_FAILURE, "WSDISPLAYIO_LDFONT"); 2282b154882Suwe close(fdev); 2292b154882Suwe } 2302b154882Suwe else { 2312b154882Suwe struct wsfthdr h; 2322b154882Suwe 2332b154882Suwe memset(&h, 0, sizeof(h)); 2342b154882Suwe strncpy(h.magic, "WSFT", sizeof(h.magic)); 2352b154882Suwe strncpy(h.name, f.name, sizeof(h.name)); 2362b154882Suwe h.firstchar = htole32(f.firstchar); 2372b154882Suwe h.numchars = htole32(f.numchars); 2382b154882Suwe h.encoding = htole32(f.encoding); 2392b154882Suwe h.fontwidth = htole32(f.fontwidth); 2402b154882Suwe h.fontheight = htole32(f.fontheight); 2412b154882Suwe h.stride = htole32(f.stride); 2422b154882Suwe h.bitorder = htole32(f.bitorder); 2432b154882Suwe h.byteorder = htole32(f.byteorder); 2442b154882Suwe 2452b154882Suwe int wsfd = open(ofile, O_WRONLY | O_CREAT | O_TRUNC, 0644); 2462b154882Suwe if (wsfd < 0) 2472b154882Suwe err(EXIT_FAILURE, "%s", ofile); 2482b154882Suwe 2492b154882Suwe ssize_t nwritten; 2502b154882Suwe nwritten = write(wsfd, &h, sizeof(h)); 2512b154882Suwe if (nwritten < 0) 2522b154882Suwe err(EXIT_FAILURE, "%s", ofile); 2532b154882Suwe if (nwritten != sizeof(h)) 2542b154882Suwe errx(EXIT_FAILURE, "%s: partial write", ofile); 2552b154882Suwe 2562b154882Suwe nwritten = write(wsfd, buffer, buflen); 2572b154882Suwe if (nwritten < 0) 2582b154882Suwe err(EXIT_FAILURE, "%s", ofile); 2592b154882Suwe if (nwritten != buflen) 2602b154882Suwe errx(EXIT_FAILURE, "%s: partial write", ofile); 2612b154882Suwe close(wsfd); 2622b154882Suwe } 263d5f9d0dbSmacallan} 264d5f9d0dbSmacallan 2652b154882Suwe 2662b154882Suwe__dead void 2672b154882Suweusage() 2682b154882Suwe{ 2692b154882Suwe fprintf(stderr, "usage: bdfload [-e encoding] [-o ofile.wsf] font.bdf\n"); 2702b154882Suwe exit(EXIT_FAILURE); 2712b154882Suwe} 2722b154882Suwe 2732b154882Suweint 274d5f9d0dbSmacallanmain(int argc, char *argv[]) 275d5f9d0dbSmacallan{ 276d5f9d0dbSmacallan FILE *foo; 2772b154882Suwe const char *encname = NULL; 2782b154882Suwe 2792b154882Suwe int c; 2802b154882Suwe while ((c = getopt(argc, argv, "e:o:")) != -1) { 2812b154882Suwe switch (c) { 2822b154882Suwe 2832b154882Suwe /* font encoding */ 2842b154882Suwe case 'e': 2852b154882Suwe if (encname != NULL) 2862b154882Suwe usage(); 2872b154882Suwe encname = optarg; 2882b154882Suwe break; 2892b154882Suwe 2902b154882Suwe /* output file name */ 2912b154882Suwe case 'o': 2922b154882Suwe if (ofile != NULL) 2932b154882Suwe usage(); 2942b154882Suwe ofile = optarg; 2952b154882Suwe break; 2962b154882Suwe 2972b154882Suwe case '?': /* FALLTHROUGH */ 2982b154882Suwe default: 2992b154882Suwe usage(); 300d5f9d0dbSmacallan } 301d5f9d0dbSmacallan } 3022b154882Suwe 3032b154882Suwe argc -= optind; 3042b154882Suwe argv += optind; 3052b154882Suwe 3062b154882Suwe if (encname == NULL) { 3072b154882Suwe encoding = WSDISPLAY_FONTENC_ISO; 3082b154882Suwe } 3092b154882Suwe else { 3102b154882Suwe for (const struct encmap *e = encmap; e->name; ++e) { 3112b154882Suwe if (strcmp(e->name, encname) == 0) { 3122b154882Suwe encoding = e->encoding; 3132b154882Suwe break; 3142b154882Suwe } 3152b154882Suwe } 3162b154882Suwe } 3172b154882Suwe 3182b154882Suwe /* get encoding from the bdf file? */ 3192b154882Suwe if (encoding == -1) 3202b154882Suwe encoding = WSDISPLAY_FONTENC_ISO; 3212b154882Suwe 3222b154882Suwe if (argc == 0) 3232b154882Suwe usage(); 3242b154882Suwe 3252b154882Suwe const char *bdfname = argv[0]; 3262b154882Suwe foo = fopen(bdfname, "r"); 3272b154882Suwe if (foo == NULL) 3282b154882Suwe err(EXIT_FAILURE, "%s", bdfname); 3292b154882Suwe 3302b154882Suwe interpret(foo); 3312b154882Suwe return EXIT_SUCCESS; 332d5f9d0dbSmacallan} 333