bdfload.c revision ce18d260
1/*	$NetBSD: bdfload.c,v 1.2 2022/05/09 15:47:27 uwe Exp $	*/
2
3/*
4 * Copyright (c) 2018 Michael Lorenz
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28/*
29 * a crude BDF loader for wsdisplay
30 */
31
32#include <stdlib.h>
33#include <stdio.h>
34#include <fcntl.h>
35#include <unistd.h>
36#include <string.h>
37#include <errno.h>
38#include <ctype.h>
39#include <sys/ioctl.h>
40#include <err.h>
41
42#include <dev/wscons/wsconsio.h>
43
44void
45interpret(FILE *foo)
46{
47	char line[128], *arg, name[64] = "foop", *buffer, buflen = -1;
48	int len, in_char = 0, current = -1, stride = 0, charsize = 0;
49	int width, height, x, y, num;
50	int first = 255, last = 0;
51	int left, top, lines;
52	int bl = 255, bt = 255, br = -1, bb = -1;
53	struct wsdisplay_font f;
54	int fdev;
55
56	while (fgets(line, sizeof(line), foo) != NULL) {
57		int i = 0;
58		/* separate keyword from parameters */
59		len = strlen(line);
60		while (!isspace(line[i]) && (i < len)) i++;
61		line[i] = 0;
62		arg = &line[i + 1];
63		i = 0;
64		len = strlen(arg);
65		/* get rid of garbage */
66		while ((!iscntrl(arg[i])) && (arg[i] != 0)) {
67			i++;
68		}
69		arg[i] = 0;
70		if (strcmp(line, "FAMILY_NAME") == 0) {
71			/* cut off quotation marks */
72			strncpy(name, arg + 1, 64);
73			name[strlen(name) - 1] = 0;
74			printf("name: %s\n", name);
75		} else if (strcmp(line, "FONTBOUNDINGBOX") == 0) {
76			int res;
77			res = sscanf(arg, "%d %d %d %d",
78					  &width, &height, &x, &y);
79			stride = (width + 7) >> 3;
80			printf("box %d x %d\n", width, height);
81			if (stride > 2) {
82				printf("no fonts wider than 16 work for now\n");
83				exit(1);
84			}
85			charsize = height * stride;
86			buflen = 256 * charsize;
87			buffer = malloc(buflen);
88			if (buffer == NULL) {
89				printf("failed to allocate %dKB for glyphs\n",
90				    buflen);
91				exit(1);
92			}
93		} else if (strcmp(line, "CHARS") == 0) {
94			if (sscanf(arg, "%d", &num) == 1)
95				printf("number of characters: %d\n", num);
96		} else if (strcmp(line, "STARTCHAR") == 0) {
97			in_char = 1;
98		} else if (strcmp(line, "ENDCHAR") == 0) {
99			in_char = 0;
100			current = -1;
101		} else if (strcmp(line, "ENCODING") == 0) {
102			if (sscanf(arg, "%d", &current) == 1) {
103				if (current >= 0 && current < 256) {
104					if (current < first) first = current;
105					if (current > last) last = current;
106				}
107			}
108		} else if (strcmp(line, "BBX") == 0) {
109			int cx, cy, cwi, che;
110			if (sscanf(arg, "%d %d %d %d", &cwi, &che, &cx, &cy)
111			     == 4) {
112				left = cx;
113				lines = che;
114				top = height + y - che - cy;
115				if (left < bl) bl = left;
116				if (top < bt) bt = top;
117				if ((left + cwi) > br) br = left + cwi;
118				if ((top + che) > bb) bb = top + che;
119			}
120		} else if (strcmp(line, "BITMAP") == 0) {
121			int i, j, k, l;
122			char num[32];
123			char *gptr = &buffer[charsize * current];
124			char *bptr = gptr + top;
125			uint16_t *bptr16 = (uint16_t *)gptr;
126			bptr16 += top;
127			/* see if the character is in range */
128			if ((current < 0) || (current > 255)) continue;
129			/* now we read & render the character */
130			for (i = 0; i < lines; i++) {
131				fgets(num, 32, foo);
132				sscanf(num, "%x", &l);
133				if ((stride) == 2 && (strlen(num) < 4))
134					l = l << 8;
135				l = l >> left;
136				if (stride == 1) {
137					*gptr = l;
138					gptr++;
139				} else {
140					*bptr16 = htobe16(l);
141					bptr16++;
142				}
143			}
144		}
145	}
146	printf("range %d to %d\n", first, last);
147	printf("actual box: %d %d %d %d\n", bl, bt, br, bb);
148	/* now stuff it into a something wsfont understands */
149	f.fontwidth = width /*(width + 3) & ~3*/;
150	f.fontheight = height;
151	f.firstchar = first;
152	f.numchars = last - first;
153	f.stride = stride;
154	f.encoding = WSDISPLAY_FONTENC_ISO;
155	f.name = name;
156	f.bitorder = WSDISPLAY_FONTORDER_L2R;
157	f.byteorder = WSDISPLAY_FONTORDER_L2R;
158	f.data = &buffer[first * charsize];
159
160	fdev = open("/dev/wsfont", O_RDWR, 0);
161	if (fdev < 0) errx(1, "unable to open /dev/wsfont");
162	ioctl(fdev, WSDISPLAYIO_LDFONT, &f);
163	close(fdev);
164}
165
166void
167main(int argc, char *argv[])
168{
169	FILE *foo;
170	if (argc > 1) {
171		foo = fopen(argv[1], "r");
172		if (foo == NULL) {
173			printf("fopen error %d\n", errno);
174			return;
175		}
176		interpret(foo);
177	} else {
178		printf("usage: bdfload <arg>\n");
179	}
180}
181