Module Name:    xsrc
Committed By:   uwe
Date:           Wed Jun  8 19:19:42 UTC 2022

Modified Files:
        xsrc/local/programs/bdfload: bdfload.c

Log Message:
bdfload: Teach it to write wsf font files.

wsfontload(8) now groks simple "wsf" file format - that is basically a
header of kinda struct wsdisplay_font but with string fields embedded
and numeric fields in little-endian and font data afterwards.

Teach bdfload to write out such files if -o file.wsf argument is
specified.

While here fix a couple of bugs too (sorry, should have been separate
commits).  Fix an off by one in numchars calculations.  Fix the type
of buflen.


To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 xsrc/local/programs/bdfload/bdfload.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: xsrc/local/programs/bdfload/bdfload.c
diff -u xsrc/local/programs/bdfload/bdfload.c:1.2 xsrc/local/programs/bdfload/bdfload.c:1.3
--- xsrc/local/programs/bdfload/bdfload.c:1.2	Mon May  9 15:47:27 2022
+++ xsrc/local/programs/bdfload/bdfload.c	Wed Jun  8 19:19:42 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: bdfload.c,v 1.2 2022/05/09 15:47:27 uwe Exp $	*/
+/*	$NetBSD: bdfload.c,v 1.3 2022/06/08 19:19:42 uwe Exp $	*/
 
 /*
  * Copyright (c) 2018 Michael Lorenz
@@ -41,17 +41,76 @@
 
 #include <dev/wscons/wsconsio.h>
 
+/*
+ * wsdisplay_font but with strings embedded and integer fields in
+ * little endian
+ */
+struct wsfthdr {
+	char magic[4];		/* "WSFT" */
+	char name[64];
+	uint32_t firstchar;
+	uint32_t numchars;
+	uint32_t encoding;
+	uint32_t fontwidth;
+	uint32_t fontheight;
+	uint32_t stride;
+	uint32_t bitorder;
+	uint32_t byteorder;
+};
+
+
+const struct encmap {
+	const char *name;
+	int encoding;
+} encmap[] = {
+	{ "cp437",	WSDISPLAY_FONTENC_IBM },
+	{ "ibm",	WSDISPLAY_FONTENC_IBM },
+	{ "iso",	WSDISPLAY_FONTENC_ISO },
+	{ "iso-8859-1",	WSDISPLAY_FONTENC_ISO },
+	{ "iso-8859-2",	WSDISPLAY_FONTENC_ISO2 },
+	{ "iso-8859-7",	WSDISPLAY_FONTENC_ISO7 },
+	{ "iso2",	WSDISPLAY_FONTENC_ISO2 },
+	{ "iso7",	WSDISPLAY_FONTENC_ISO7 },
+	{ "iso8859-1",	WSDISPLAY_FONTENC_ISO },
+	{ "iso8859-2",	WSDISPLAY_FONTENC_ISO2 },
+	{ "iso8859-7",	WSDISPLAY_FONTENC_ISO7 },
+	{ "koi8-r",	WSDISPLAY_FONTENC_KOI8_R },
+	{ "koi8r",	WSDISPLAY_FONTENC_KOI8_R },
+	{ "latin-1",	WSDISPLAY_FONTENC_ISO },
+	{ "latin-2",	WSDISPLAY_FONTENC_ISO2 },
+	{ "latin1",	WSDISPLAY_FONTENC_ISO },
+	{ "latin2",	WSDISPLAY_FONTENC_ISO2 },
+	{ "pcvt",	WSDISPLAY_FONTENC_PCVT },
+	{ NULL, -1 }
+};
+
+const char * const encname[] = {
+#define _ENC(_e) [_e] = #_e
+	_ENC(WSDISPLAY_FONTENC_ISO),
+	_ENC(WSDISPLAY_FONTENC_IBM),
+	_ENC(WSDISPLAY_FONTENC_PCVT),
+	_ENC(WSDISPLAY_FONTENC_ISO7),
+	_ENC(WSDISPLAY_FONTENC_ISO2),
+	_ENC(WSDISPLAY_FONTENC_KOI8_R),
+};
+
+
+const char *ofile = NULL;
+int encoding = -1;
+
+
 void
 interpret(FILE *foo)
 {
-	char line[128], *arg, name[64] = "foop", *buffer, buflen = -1;
+	char line[128], *arg, name[64] = "foop", *buffer;
+	int buflen = -1;
 	int len, in_char = 0, current = -1, stride = 0, charsize = 0;
 	int width, height, x, y, num;
 	int first = 255, last = 0;
 	int left, top, lines;
 	int bl = 255, bt = 255, br = -1, bb = -1;
 	struct wsdisplay_font f;
-	int fdev;
+	int status;
 
 	while (fgets(line, sizeof(line), foo) != NULL) {
 		int i = 0;
@@ -84,7 +143,7 @@ interpret(FILE *foo)
 			}
 			charsize = height * stride;
 			buflen = 256 * charsize;
-			buffer = malloc(buflen);
+			buffer = calloc(1, buflen);
 			if (buffer == NULL) {
 				printf("failed to allocate %dKB for glyphs\n",
 				    buflen);
@@ -144,37 +203,130 @@ interpret(FILE *foo)
 		}
 	}
 	printf("range %d to %d\n", first, last);
+	printf("encoding: %s\n", encname[encoding]);
 	printf("actual box: %d %d %d %d\n", bl, bt, br, bb);
+
 	/* now stuff it into a something wsfont understands */
 	f.fontwidth = width /*(width + 3) & ~3*/;
 	f.fontheight = height;
 	f.firstchar = first;
-	f.numchars = last - first;
+	f.numchars = last - first + 1;
 	f.stride = stride;
-	f.encoding = WSDISPLAY_FONTENC_ISO;
+	f.encoding = encoding;
 	f.name = name;
 	f.bitorder = WSDISPLAY_FONTORDER_L2R;
 	f.byteorder = WSDISPLAY_FONTORDER_L2R;
 	f.data = &buffer[first * charsize];
 
-	fdev = open("/dev/wsfont", O_RDWR, 0);
-	if (fdev < 0) errx(1, "unable to open /dev/wsfont");
-	ioctl(fdev, WSDISPLAYIO_LDFONT, &f);
-	close(fdev);
+	if (ofile == NULL) {
+		int fdev = open("/dev/wsfont", O_RDWR, 0);
+		if (fdev < 0)
+			err(EXIT_FAILURE, "/dev/wsfont");
+		status = ioctl(fdev, WSDISPLAYIO_LDFONT, &f);
+		if (status != 0)
+			err(EXIT_FAILURE, "WSDISPLAYIO_LDFONT");
+		close(fdev);
+	}
+	else {
+		struct wsfthdr h;
+
+		memset(&h, 0, sizeof(h));
+		strncpy(h.magic, "WSFT", sizeof(h.magic));
+		strncpy(h.name, f.name, sizeof(h.name));
+		h.firstchar = htole32(f.firstchar);
+		h.numchars = htole32(f.numchars);
+		h.encoding = htole32(f.encoding);
+		h.fontwidth = htole32(f.fontwidth);
+		h.fontheight = htole32(f.fontheight);
+		h.stride = htole32(f.stride);
+		h.bitorder = htole32(f.bitorder);
+		h.byteorder = htole32(f.byteorder);
+
+		int wsfd = open(ofile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+		if (wsfd < 0)
+			err(EXIT_FAILURE, "%s", ofile);
+
+		ssize_t nwritten;
+		nwritten = write(wsfd, &h, sizeof(h));
+		if (nwritten < 0)
+			err(EXIT_FAILURE, "%s", ofile);
+		if (nwritten != sizeof(h))
+			errx(EXIT_FAILURE, "%s: partial write", ofile);
+
+		nwritten = write(wsfd, buffer, buflen);
+		if (nwritten < 0)
+			err(EXIT_FAILURE, "%s", ofile);
+		if (nwritten != buflen)
+			errx(EXIT_FAILURE, "%s: partial write", ofile);
+		close(wsfd);
+	}
 }
 
-void
+
+__dead void
+usage()
+{
+	fprintf(stderr, "usage: bdfload [-e encoding] [-o ofile.wsf] font.bdf\n");
+	exit(EXIT_FAILURE);
+}
+
+int
 main(int argc, char *argv[])
 {
 	FILE *foo;
-	if (argc > 1) {
-		foo = fopen(argv[1], "r");
-		if (foo == NULL) {
-			printf("fopen error %d\n", errno);
-			return;
+	const char *encname = NULL;
+
+	int c;
+	while ((c = getopt(argc, argv, "e:o:")) != -1) {
+		switch (c) {
+
+		/* font encoding */
+		case 'e':
+			if (encname != NULL)
+				usage();
+			encname = optarg;
+			break;
+
+		/* output file name */
+		case 'o':
+			if (ofile != NULL)
+				usage();
+			ofile = optarg;
+			break;
+
+		case '?':	/* FALLTHROUGH */
+		default:
+			usage();
 		}
-		interpret(foo);
-	} else {
-		printf("usage: bdfload <arg>\n");
 	}
+
+	argc -= optind;
+	argv += optind;
+
+	if (encname == NULL) {
+		encoding = WSDISPLAY_FONTENC_ISO;
+	}
+	else {
+		for (const struct encmap *e = encmap; e->name; ++e) {
+			if (strcmp(e->name, encname) == 0) {
+				encoding = e->encoding;
+				break;
+			}
+		}
+	}
+
+	/* get encoding from the bdf file? */
+	if (encoding == -1)
+		encoding = WSDISPLAY_FONTENC_ISO;
+
+	if (argc == 0)
+		usage();
+
+	const char *bdfname = argv[0];
+	foo = fopen(bdfname, "r");
+	if (foo == NULL)
+		err(EXIT_FAILURE, "%s", bdfname);
+
+	interpret(foo);
+	return EXIT_SUCCESS;
 }

Reply via email to