Module Name:    xsrc
Committed By:   macallan
Date:           Mon Jan  8 18:09:33 UTC 2024

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

Log Message:
add support for doubling a font's size, with optional smoothing
- works only on fonts up to 8 pixels wide for now
- smoothing attempts to detect pixel staircases and add pixels to smooth
  them out


To generate a diff of this commit:
cvs rdiff -u -r1.20 -r1.21 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.20 xsrc/local/programs/bdfload/bdfload.c:1.21
--- xsrc/local/programs/bdfload/bdfload.c:1.20	Thu Jul 27 08:44:42 2023
+++ xsrc/local/programs/bdfload/bdfload.c	Mon Jan  8 18:09:33 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: bdfload.c,v 1.20 2023/07/27 08:44:42 macallan Exp $	*/
+/*	$NetBSD: bdfload.c,v 1.21 2024/01/08 18:09:33 macallan Exp $	*/
 
 /*
  * Copyright (c) 2018 Michael Lorenz
@@ -103,6 +103,8 @@ int verbose = 0;
 int dump = 0;
 int header = 0;
 int force = 0;
+int scale = 0;
+int smoothe = 0;
 char commentbuf[2048] = "";
 int commentptr = 0;
 char fontname[64] = "";
@@ -125,9 +127,11 @@ dump_line(char *gptr, int stride)
 }
  
 void
-write_wsf(const char *oname, struct wsdisplay_font *f, char *buffer, int buflen)
+write_wsf(const char *oname, struct wsdisplay_font *f)
 {
 	struct wsfthdr h;
+	uint8_t *buffer = f->data;
+	int buflen = f->numchars * f->stride * f->fontheight;
 
 	memset(&h, 0, sizeof(h));
 	strncpy(h.magic, "WSFT", sizeof(h.magic));
@@ -161,10 +165,10 @@ write_wsf(const char *oname, struct wsdi
 }
 
 int
-write_header(const char *filename, struct wsdisplay_font *f, 
-             char *buffer, int buflen)
+write_header(const char *filename, struct wsdisplay_font *f)
 {
 	FILE *output;
+	char *buffer = f->data;
 	int i, j, x, y, idx, pxls, left;
 	char name[64], c, msk;
 	
@@ -200,11 +204,11 @@ write_header(const char *filename, struc
 	fprintf(output, "\t%s_data\t\t/* data */\n", name);
 	fprintf(output, "};\n\n");
 	fprintf(output, "static u_char %s_data[] = {\n", name);
-	for (i = f->firstchar; i < f->firstchar + f->numchars; i++) {
+	for (i = 0; i < f->numchars; i++) {
 		if (names[i] != NULL) {
-			fprintf(output, "\t/* %d %s */\n", i, names[i]);
+			fprintf(output, "\t/* %d %s */\n", i + f->firstchar, names[i]);
 		} else			
-			fprintf(output, "\t/* %d */\n", i);
+			fprintf(output, "\t/* %d */\n", i + f->firstchar);
 		idx = i * f->stride * f->fontheight;
 		for (y = 0; y < f->fontheight; y++) {
 			for (x = 0; x < f->stride; x++) {
@@ -234,6 +238,79 @@ write_header(const char *filename, struc
 }
 
 void
+double_pixels(uint8_t *inbuf, uint16_t *outbuf, int bytes)
+{
+	int i, j;
+	uint16_t outmask, out;
+	uint8_t in, inmask;
+
+	for (i = 0; i < bytes; i++) {
+		inmask = 0x80;
+		outmask = 0xc000;
+		out = 0;
+		in = inbuf[i];
+		for (j = 0; j < 8; j++) {
+			if (in & inmask) {
+				out |= outmask;
+			}
+			inmask = inmask >> 1;
+			outmask = outmask >> 2;
+		}
+		outbuf[i * 2] = htobe16(out);
+	}
+}
+
+void fill_dup(uint16_t *buf, int lines)
+{
+	int i;
+	for (i = 0; i < lines; i++) {
+		buf[2 * i + 1] = buf[2 * i];
+	}
+}
+
+void smoothe_pixels(uint16_t *buf, int lines)
+{
+	int i, j, topright, topleft, botright, botleft;
+	uint16_t pmask, in, prev, next, out;
+	for (i = 0; i < lines; i++) {
+		pmask = 0xc000;
+		in = be16toh(buf[i]);
+		out = in;
+		prev = next = 0;
+		if (i > 1) prev = be16toh(buf[i - 2]);
+		if (i < (lines - 2)) next = be16toh(buf[i + 2]);
+		for (j = 0; j < 8; j++) {
+			if ((in & pmask) == 0) {
+				/* empty pixel, check surroundings */
+				topright = topleft = botright = botleft = 0;
+				if (((i & 1) == 0) && (j < 6))
+					topright = (((prev & pmask) == pmask) &&
+						    ((prev & (pmask >> 2)) != 0) &&
+						    ((in & (pmask >> 2)) != 0));
+				if (((i & 1) == 0) && (j > 0))
+					topleft = (((prev & pmask) == pmask) &&
+						    ((prev & (pmask << 2)) != 0) &&
+						    ((in & (pmask << 2)) != 0));
+				if ((i & 1) && (j < 6))
+					botright = (((next & pmask) == pmask) &&
+						    ((next & (pmask >> 2)) != 0) &&
+						    ((in & (pmask >> 2)) != 0));
+				if ((i & 1) && (j > 0))
+					botleft = (((next & pmask) == pmask) &&
+						    ((next & (pmask << 2)) != 0) &&
+						    ((in & (pmask << 2)) != 0));
+				if ((topright + topleft + botright + botleft) == 1) {
+					if (topleft || botleft) out |= pmask << 1;
+					if (topright || botright) out |= pmask >> 1;
+				}
+			}
+			pmask = pmask >> 2;
+		}
+		buf[i] = htobe16(out);
+	}
+}
+
+void
 interpret(FILE *foo)
 {
 	char line[128], *arg, name[64] = "foo", *buffer, *cbitmap;
@@ -404,18 +481,59 @@ interpret(FILE *foo)
 	}
 
 	/* now stuff it into a something wsfont understands */
-	f.fontwidth = width /*(width + 3) & ~3*/;
-	f.fontheight = height;
 	f.firstchar = first;
 	f.numchars = last - first + 1;
-	f.stride = stride;
 	f.encoding = encoding;
 	if (fontname[0] == 0) {
 		f.name = name;
 	} else f.name = fontname;
 	f.bitorder = WSDISPLAY_FONTORDER_L2R;
 	f.byteorder = WSDISPLAY_FONTORDER_L2R;
-	f.data = &buffer[first * charsize];
+
+	if (scale) {
+		uint16_t *outbuf;
+		uint8_t *inbuf;
+		int i;
+
+		if (stride != 1) err(EXIT_FAILURE,
+		    "scaling works only on fonts up to 8 pixels wide\n");
+		f.fontwidth = width * 2 /*(width + 3) & ~3*/;
+		f.fontheight = height * 2;
+		f.stride = stride * 2;
+		outbuf = calloc(1, f.numchars * charsize * 4);
+		if (outbuf == NULL) err(EXIT_FAILURE, 
+		    "failed to allocete memory for scale buffer\n");
+		f.data = outbuf;
+		inbuf = &buffer[first * charsize];
+		for (i = 0; i < f.numchars; i++) {
+			double_pixels(inbuf, outbuf, charsize);
+			fill_dup(outbuf, charsize);
+			if (smoothe) smoothe_pixels(outbuf, charsize * 2);
+			inbuf += charsize;
+			outbuf += charsize * 2;
+		}
+		
+	} else {
+		f.fontwidth = width /*(width + 3) & ~3*/;
+		f.fontheight = height;
+		f.stride = stride;
+		f.data = &buffer[first * charsize];
+	}
+if (0) {
+	int i;
+	uint16_t pixbuf[16];
+	double_pixels(&buffer[charsize * 'Q'], pixbuf, charsize);
+	fill_dup(pixbuf, charsize);
+	for (i = 0; i < charsize * 2; i++) {	
+		printf("%2d: ", i);
+		dump_line((char *)&pixbuf[i], 2); 
+	}
+	smoothe_pixels(pixbuf, charsize * 2);
+	for (i = 0; i < charsize * 2; i++) {	
+		printf("%2d: ", i);
+		dump_line((char *)&pixbuf[i], 2); 
+	}
+}
 
 	if (ofile == NULL) {
 		int fdev = open("/dev/wsfont", O_RDWR, 0);
@@ -428,16 +546,16 @@ interpret(FILE *foo)
 	}
 	else {
 		if (header == 0)
-			write_wsf(ofile, &f, buffer, buflen);
+			write_wsf(ofile, &f);
 		else
-			write_header(ofile, &f, buffer, buflen);
+			write_header(ofile, &f);
 	}
 }
 
 __dead void
 usage()
 {
-	fprintf(stderr, "Usage: %s [-vdhf] [-e encoding] [-N name] "
+	fprintf(stderr, "Usage: %s [-vdhf2s] [-e encoding] [-N name] "
 	    "[-o ofile.wsf] font.bdf\n", getprogname());
 	exit(EXIT_FAILURE);
 }
@@ -449,7 +567,7 @@ main(int argc, char *argv[])
 	const char *encname = NULL;
 
 	int c;
-	while ((c = getopt(argc, argv, "e:o:N:vdhf")) != -1) {
+	while ((c = getopt(argc, argv, "e:o:N:vdhf2s")) != -1) {
 		switch (c) {
 
 		/* font encoding */
@@ -480,6 +598,12 @@ main(int argc, char *argv[])
 		case 'f':
 			force = 1;
 			break;
+		case '2':
+			scale = 1;
+			break;
+		case 's':
+			smoothe = 1;
+			break;
 		case 'N':
 			strncpy(fontname, optarg, 64);
 			break;

Reply via email to