xref: /netbsd-src/sys/dev/wsfont/wsfont.c (revision 627f7eb200a4419d89b531d55fccd2ee3ffdcde0)
1 /* 	$NetBSD: wsfont.c,v 1.71 2020/11/23 12:15:39 rin Exp $	*/
2 
3 /*-
4  * Copyright (c) 1999, 2000, 2001, 2002 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Andrew Doran.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: wsfont.c,v 1.71 2020/11/23 12:15:39 rin Exp $");
34 
35 #include "opt_wsfont.h"
36 
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/time.h>
40 #include <sys/malloc.h>
41 #include <sys/queue.h>
42 
43 #include <dev/wscons/wsdisplayvar.h>
44 #include <dev/wscons/wsconsio.h>
45 #include <dev/wsfont/wsfont.h>
46 
47 #include "wsfont_glue.h"	/* NRASOPS_ROTATION */
48 
49 #undef HAVE_FONT
50 
51 #ifdef FONT_QVSS8x15
52 #define HAVE_FONT 1
53 #include <dev/wsfont/qvss8x15.h>
54 #endif
55 
56 #ifdef FONT_GALLANT12x22
57 #define HAVE_FONT 1
58 #include <dev/wsfont/gallant12x22.h>
59 #endif
60 
61 #ifdef FONT_LUCIDA16x29
62 #define HAVE_FONT 1
63 #include <dev/wsfont/lucida16x29.h>
64 #endif
65 
66 #ifdef FONT_VT220L8x8
67 #define HAVE_FONT 1
68 #include <dev/wsfont/vt220l8x8.h>
69 #endif
70 
71 #ifdef FONT_VT220L8x10
72 #define HAVE_FONT 1
73 #include <dev/wsfont/vt220l8x10.h>
74 #endif
75 
76 #ifdef FONT_VT220L8x16
77 #define HAVE_FONT 1
78 #include <dev/wsfont/vt220l8x16.h>
79 #endif
80 
81 #ifdef FONT_VT220ISO8x8
82 #define HAVE_FONT 1
83 #include <dev/wsfont/vt220iso8x8.h>
84 #endif
85 
86 #ifdef FONT_VT220ISO8x16
87 #define HAVE_FONT 1
88 #include <dev/wsfont/vt220iso8x16.h>
89 #endif
90 
91 #ifdef FONT_VT220KOI8x10_KOI8_R
92 #define HAVE_FONT 1
93 #include <dev/wsfont/vt220koi8x10.h>
94 #endif
95 
96 #ifdef FONT_VT220KOI8x10_KOI8_U
97 #define HAVE_FONT 1
98 #define KOI8_U
99 #include <dev/wsfont/vt220koi8x10.h>
100 #undef KOI8_U
101 #endif
102 
103 #ifdef FONT_SONY8x16
104 #define HAVE_FONT 1
105 #include <dev/wsfont/sony8x16.h>
106 #endif
107 
108 #ifdef FONT_SONY12x24
109 #define HAVE_FONT 1
110 #include <dev/wsfont/sony12x24.h>
111 #endif
112 
113 #ifdef FONT_OMRON12x20
114 #define HAVE_FONT 1
115 #include <dev/wsfont/omron12x20.h>
116 #endif
117 
118 #ifdef FONT_GLASS10x19
119 #define HAVE_FONT 1
120 #include <dev/wsfont/glass10x19.h>
121 #endif
122 
123 #ifdef FONT_GLASS10x25
124 #define HAVE_FONT 1
125 #include <dev/wsfont/glass10x25.h>
126 #endif
127 
128 #ifdef FONT_DEJAVU_SANS_MONO12x22
129 #define HAVE_FONT 1
130 #include <dev/wsfont/DejaVu_Sans_Mono_12x22.h>
131 #endif
132 
133 #ifdef FONT_DROID_SANS_MONO12x22
134 #define HAVE_FONT 1
135 #include <dev/wsfont/Droid_Sans_Mono_12x22.h>
136 #endif
137 
138 #ifdef FONT_DROID_SANS_MONO9x18
139 #define HAVE_FONT 1
140 #include <dev/wsfont/Droid_Sans_Mono_9x18.h>
141 #endif
142 
143 #ifdef FONT_DROID_SANS_MONO19x36
144 #define HAVE_FONT 1
145 #include <dev/wsfont/Droid_Sans_Mono_19x36.h>
146 #endif
147 
148 #ifdef FONT_GO_MONO12x23
149 #define HAVE_FONT 1
150 #include <dev/wsfont/Go_Mono_12x23.h>
151 #endif
152 
153 #ifdef FONT_SPLEEN5x8
154 #define HAVE_FONT 1
155 #include <dev/wsfont/spleen5x8.h>
156 #endif
157 
158 #ifdef FONT_SPLEEN6x12
159 #define HAVE_FONT 1
160 #include <dev/wsfont/spleen6x12.h>
161 #endif
162 
163 #ifdef FONT_SPLEEN8x16
164 #define HAVE_FONT 1
165 #include <dev/wsfont/spleen8x16.h>
166 #endif
167 
168 #ifdef FONT_SPLEEN12x24
169 #define HAVE_FONT 1
170 #include <dev/wsfont/spleen12x24.h>
171 #endif
172 
173 #ifdef FONT_SPLEEN16x32
174 #define HAVE_FONT 1
175 #include <dev/wsfont/spleen16x32.h>
176 #endif
177 
178 #ifdef FONT_SPLEEN32x64
179 #define HAVE_FONT 1
180 #include <dev/wsfont/spleen32x64.h>
181 #endif
182 
183 #ifdef FONT_LIBERATION_MONO12x21
184 #define HAVE_FONT 1
185 #include <dev/wsfont/Liberation_Mono_12x21.h>
186 #endif
187 
188 #ifdef FONT_BOLD16x32
189 #define HAVE_FONT 1
190 #include <dev/wsfont/bold16x32.h>
191 #endif
192 
193 /* Make sure we always have at least one bitmap font. */
194 #ifndef HAVE_FONT
195 #define HAVE_FONT 1
196 #define FONT_BOLD8x16 1
197 #endif
198 
199 #ifdef FONT_BOLD8x16
200 #include <dev/wsfont/bold8x16.h>
201 #endif
202 
203 #define	WSFONT_IDENT_MASK	0xffffff00
204 #define	WSFONT_IDENT_SHIFT	8
205 #define	WSFONT_BITO_MASK	0x000000f0
206 #define	WSFONT_BITO_SHIFT	4
207 #define	WSFONT_BYTEO_MASK	0x0000000f
208 #define	WSFONT_BYTEO_SHIFT	0
209 
210 #define WSFONT_BUILTIN	0x01	/* In wsfont.c */
211 #define WSFONT_STATIC	0x02	/* Font structures not malloc()ed */
212 #define WSFONT_COPY	0x04	/* Copy of existing font in table */
213 
214 /* Placeholder struct used for linked list */
215 struct font {
216 	TAILQ_ENTRY(font) chain;
217 	struct	wsdisplay_font *font;
218 	u_int	lockcount;
219 	u_int	cookie;
220 	u_int	flags;
221 };
222 
223 /* Our list of built-in fonts */
224 static struct font builtin_fonts[] = {
225 #ifdef FONT_BOLD8x16
226 	{ { NULL, NULL }, &bold8x16, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN  },
227 #endif
228 #ifdef FONT_BOLD16x32
229 	{ { NULL, NULL }, &bold16x32, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN  },
230 #endif
231 #ifdef FONT_GALLANT12x22
232 	{ { NULL, NULL }, &gallant12x22, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
233 #endif
234 #ifdef FONT_LUCIDA16x29
235 	{ { NULL, NULL }, &lucida16x29, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
236 #endif
237 #ifdef FONT_QVSS8x15
238 	{ { NULL, NULL }, &qvss8x15, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
239 #endif
240 #ifdef FONT_VT220L8x8
241 	{ { NULL, NULL }, &vt220l8x8, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
242 #endif
243 #ifdef FONT_VT220L8x10
244 	{ { NULL, NULL }, &vt220l8x10, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
245 #endif
246 #ifdef FONT_VT220L8x16
247 	{ { NULL, NULL }, &vt220l8x16, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
248 #endif
249 #ifdef FONT_VT220ISO8x8
250 	{ { NULL, NULL }, &vt220iso8x8, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
251 #endif
252 #ifdef FONT_VT220ISO8x16
253 	{ { NULL, NULL }, &vt220iso8x16, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
254 #endif
255 #ifdef FONT_VT220KOI8x10_KOI8_R
256 	{ { NULL, NULL }, &vt220kr8x10, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
257 #endif
258 #ifdef FONT_VT220KOI8x10_KOI8_U
259 	{ { NULL, NULL }, &vt220ku8x10, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
260 #endif
261 #ifdef FONT_SONY8x16
262 	{ { NULL, NULL }, &sony8x16, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
263 #endif
264 #ifdef FONT_SONY12x24
265 	{ { NULL, NULL }, &sony12x24, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
266 #endif
267 #ifdef FONT_OMRON12x20
268 	{ { NULL, NULL }, &omron12x20, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
269 #endif
270 #ifdef FONT_GLASS10x19
271 	{ { NULL, NULL }, &Glass_TTY_VT220_10x19, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
272 #endif
273 #ifdef FONT_GLASS10x25
274 	{ { NULL, NULL }, &Glass_TTY_VT220_10x25, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
275 #endif
276 #ifdef FONT_DEJAVU_SANS_MONO12x22
277 	{ { NULL, NULL }, &DejaVu_Sans_Mono_12x22, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
278 #endif
279 #ifdef FONT_DROID_SANS_MONO12x22
280 	{ { NULL, NULL }, &Droid_Sans_Mono_12x22, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
281 #endif
282 #ifdef FONT_DROID_SANS_MONO9x18
283 	{ { NULL, NULL }, &Droid_Sans_Mono_9x18, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
284 #endif
285 #ifdef FONT_DROID_SANS_MONO19x36
286 	{ { NULL, NULL }, &Droid_Sans_Mono_19x36, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
287 #endif
288 #ifdef FONT_GO_MONO12x23
289 	{ { NULL, NULL }, &Go_Mono_12x23, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
290 #endif
291 #ifdef FONT_SPLEEN5x8
292 	{ { NULL, NULL }, &spleen5x8, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
293 #endif
294 #ifdef FONT_SPLEEN6x12
295 	{ { NULL, NULL }, &spleen6x12, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
296 #endif
297 #ifdef FONT_SPLEEN8x16
298 	{ { NULL, NULL }, &spleen8x16, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
299 #endif
300 #ifdef FONT_SPLEEN12x24
301 	{ { NULL, NULL }, &spleen12x24, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
302 #endif
303 #ifdef FONT_SPLEEN16x32
304 	{ { NULL, NULL }, &spleen16x32, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
305 #endif
306 #ifdef FONT_SPLEEN32x64
307 	{ { NULL, NULL }, &spleen32x64, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
308 #endif
309 #ifdef FONT_LIBERATION_MONO12x21
310 	{ { NULL, NULL }, &Liberation_Mono_12x21, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
311 #endif
312 	{ { NULL, NULL }, NULL, 0, 0, 0 },
313 };
314 
315 static TAILQ_HEAD(,font)	list;
316 static int	ident;
317 
318 /* Reverse the bit order in a byte */
319 static const u_char reverse[256] = {
320 	0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
321 	0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
322 	0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
323 	0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
324 	0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
325 	0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
326 	0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
327 	0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
328 	0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
329 	0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
330 	0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
331 	0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
332 	0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
333 	0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
334 	0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
335 	0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
336 	0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
337 	0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
338 	0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
339 	0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
340 	0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
341 	0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
342 	0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
343 	0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
344 	0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
345 	0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
346 	0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
347 	0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
348 	0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
349 	0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
350 	0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
351 	0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
352 };
353 
354 static struct	font *wsfont_find0(int, int);
355 static struct	font *wsfont_add0(struct wsdisplay_font *, int);
356 static void	wsfont_revbit(struct wsdisplay_font *);
357 static void	wsfont_revbyte(struct wsdisplay_font *);
358 
359 int
360 wsfont_make_cookie(int cident, int bito, int byteo)
361 {
362 
363 	return ((cident & WSFONT_IDENT_MASK) |
364 	    (bito << WSFONT_BITO_SHIFT) |
365 	    (byteo << WSFONT_BYTEO_SHIFT));
366 }
367 
368 static void
369 wsfont_revbit(struct wsdisplay_font *font)
370 {
371 	u_char *p, *m;
372 
373 	p = (u_char *)font->data;
374 	m = p + font->stride * font->numchars * font->fontheight;
375 
376 	for (; p < m; p++)
377 		*p = reverse[*p];
378 }
379 
380 static void
381 wsfont_revbyte(struct wsdisplay_font *font)
382 {
383 	int x, l, r, nr;
384 	u_char *rp;
385 
386 	if (font->stride == 1)
387 		return;
388 
389 	rp = (u_char *)font->data;
390 	nr = font->numchars * font->fontheight;
391 
392 	while (nr--) {
393 		l = 0;
394 		r = font->stride - 1;
395 
396 		while (l < r) {
397 			x = rp[l];
398 			rp[l] = rp[r];
399 			rp[r] = x;
400 			l++, r--;
401 		}
402 
403 		rp += font->stride;
404 	}
405 }
406 
407 void
408 wsfont_enum(void (*cb)(const char *, int, int, int))
409 {
410 	struct wsdisplay_font *f;
411 	struct font *ent;
412 
413 	TAILQ_FOREACH(ent, &list, chain) {
414 		f = ent->font;
415 		cb(f->name, f->fontwidth, f->fontheight, f->stride);
416 	}
417 }
418 
419 #if NRASOPS_ROTATION > 0
420 
421 struct wsdisplay_font *wsfont_rotate_cw_internal(struct wsdisplay_font *);
422 struct wsdisplay_font *wsfont_rotate_ccw_internal(struct wsdisplay_font *);
423 
424 struct wsdisplay_font *
425 wsfont_rotate_cw_internal(struct wsdisplay_font *font)
426 {
427 	int b, n, r, namelen, newstride;
428 	struct wsdisplay_font *newfont;
429 	char *newname, *newbits;
430 
431 	/* Duplicate the existing font... */
432 	newfont = malloc(sizeof(*font), M_DEVBUF, M_WAITOK);
433 
434 	*newfont = *font;
435 
436 	namelen = strlen(font->name) + 4;
437 	newname = malloc(namelen, M_DEVBUF, M_WAITOK);
438 	strlcpy(newname, font->name, namelen);
439 	strlcat(newname, "cw", namelen);
440 	newfont->name = newname;
441 
442 	/* Allocate a buffer big enough for the rotated font. */
443 	newstride = (font->fontheight + 7) / 8;
444 	newbits = malloc(newstride * font->fontwidth * font->numchars,
445 	    M_DEVBUF, M_WAITOK|M_ZERO);
446 
447 	/* Rotate the font a bit at a time. */
448 	for (n = 0; n < font->numchars; n++) {
449 		unsigned char *ch = (unsigned char *)font->data +
450 		    (n * font->stride * font->fontheight);
451 
452 		for (r = 0; r < font->fontheight; r++) {
453 			for (b = 0; b < font->fontwidth; b++) {
454 				unsigned char *rb;
455 
456 				rb = ch + (font->stride * r) + (b / 8);
457 				if (*rb & (0x80 >> (b % 8))) {
458 					unsigned char *rrb;
459 
460 					rrb = newbits + newstride - 1 - (r / 8)
461 					    + (n * newstride * font->fontwidth)
462 					    + (newstride * b);
463 					*rrb |= (1 << (r % 8));
464 				}
465 			}
466 		}
467 	}
468 
469 	newfont->data = newbits;
470 
471 	/* Update font sizes. */
472 	newfont->stride = newstride;
473 	newfont->fontwidth = font->fontheight;
474 	newfont->fontheight = font->fontwidth;
475 
476 	if (wsfont_add(newfont, 0) != 0) {
477 		/*
478 		 * If we seem to have rotated this font already, drop the
479 		 * new one...
480 		 */
481 		free(newbits, M_DEVBUF);
482 		free(newfont, M_DEVBUF);
483 		newfont = NULL;
484 	}
485 
486 	return (newfont);
487 }
488 
489 struct wsdisplay_font *
490 wsfont_rotate_ccw_internal(struct wsdisplay_font *font)
491 {
492 	int b, n, r, namelen, newstride;
493 	struct wsdisplay_font *newfont;
494 	char *newname, *newbits;
495 
496 	/* Duplicate the existing font... */
497 	newfont = malloc(sizeof(*font), M_DEVBUF, M_WAITOK);
498 
499 	*newfont = *font;
500 
501 	namelen = strlen(font->name) + 4;
502 	newname = malloc(namelen, M_DEVBUF, M_WAITOK);
503 	strlcpy(newname, font->name, namelen);
504 	strlcat(newname, "ccw", namelen);
505 	newfont->name = newname;
506 
507 	/* Allocate a buffer big enough for the rotated font. */
508 	newstride = (font->fontheight + 7) / 8;
509 	newbits = malloc(newstride * font->fontwidth * font->numchars,
510 	    M_DEVBUF, M_WAITOK|M_ZERO);
511 
512 	/* Rotate the font a bit at a time. */
513 	for (n = 0; n < font->numchars; n++) {
514 		unsigned char *ch = (unsigned char *)font->data +
515 		    (n * font->stride * font->fontheight);
516 
517 		for (r = 0; r < font->fontheight; r++) {
518 			for (b = 0; b < font->fontwidth; b++) {
519 				unsigned char *rb;
520 
521 				rb = ch + (font->stride * r) + (b / 8);
522 				if (*rb & (0x80 >> (b % 8))) {
523 					unsigned char *rrb;
524 					int w = font->fontwidth;
525 
526 					rrb = newbits + (r / 8)
527 					    + (n * newstride * w)
528 					    + (newstride * (w - 1 - b));
529 					*rrb |= (0x80 >> (r % 8));
530 				}
531 			}
532 		}
533 	}
534 
535 	newfont->data = newbits;
536 
537 	/* Update font sizes. */
538 	newfont->stride = newstride;
539 	newfont->fontwidth = font->fontheight;
540 	newfont->fontheight = font->fontwidth;
541 
542 	if (wsfont_add(newfont, 0) != 0) {
543 		/*
544 		 * If we seem to have rotated this font already, drop the
545 		 * new one...
546 		 */
547 		free(newbits, M_DEVBUF);
548 		free(newfont, M_DEVBUF);
549 		newfont = NULL;
550 	}
551 
552 	return (newfont);
553 }
554 
555 int
556 wsfont_rotate(int cookie, int rotate)
557 {
558 	int s, ncookie;
559 	struct wsdisplay_font *font;
560 	struct font *origfont;
561 
562 	s = splhigh();
563 	origfont = wsfont_find0(cookie, 0xffffffff);
564 	splx(s);
565 
566 	switch (rotate) {
567 	case WSFONT_ROTATE_CW:
568 		font = wsfont_rotate_cw_internal(origfont->font);
569 		if (font == NULL)
570 			return (-1);
571 		break;
572 
573 	case WSFONT_ROTATE_CCW:
574 		font = wsfont_rotate_ccw_internal(origfont->font);
575 		if (font == NULL)
576 			return (-1);
577 		break;
578 
579 	case WSFONT_ROTATE_UD:
580 	default:
581 		return (-1);
582 	}
583 	/* rotation works only with bitmap fonts so far */
584 	ncookie = wsfont_find(font->name, font->fontwidth, font->fontheight,
585 	    font->stride, 0, 0, WSFONT_FIND_BITMAP);
586 
587 	return (ncookie);
588 }
589 
590 #endif	/* NRASOPS_ROTATION */
591 
592 void
593 wsfont_init(void)
594 {
595 	struct font *ent;
596 	static int again;
597 	int i;
598 
599 	if (again != 0)
600 		return;
601 	again = 1;
602 
603 	TAILQ_INIT(&list);
604 	ent = builtin_fonts;
605 
606 	for (i = 0; builtin_fonts[i].font != NULL; i++, ent++) {
607 		ident += (1 << WSFONT_IDENT_SHIFT);
608 		ent->cookie = wsfont_make_cookie(ident,
609 		    ent->font->bitorder, ent->font->byteorder);
610 		TAILQ_INSERT_TAIL(&list, ent, chain);
611 	}
612 }
613 
614 static struct font *
615 wsfont_find0(int cookie, int mask)
616 {
617 	struct font *ent;
618 
619 	TAILQ_FOREACH(ent, &list, chain) {
620 		if ((ent->cookie & mask) == (cookie & mask))
621 			return (ent);
622 	}
623 
624 	return (NULL);
625 }
626 
627 int
628 wsfont_matches(struct wsdisplay_font *font, const char *name,
629 	       int width, int height, int stride, int flags)
630 {
631 	int score = 20000;
632 
633 	/* first weed out fonts the caller doesn't claim support for */
634 	if (FONT_IS_ALPHA(font)) {
635 		if (flags & WSFONT_PREFER_ALPHA)
636 			score++;
637 		if ((flags & WSFONT_FIND_ALPHA) == 0)
638 			return 0;
639 	} else {
640 		if ((flags & WSFONT_FIND_BITMAP) == 0)
641 			return 0;
642 	}
643 
644 	if (height != 0 && font->fontheight != height)
645 		return (0);
646 
647 	if (width != 0) {
648 		if ((flags & WSFONT_FIND_BESTWIDTH) == 0) {
649 			if (font->fontwidth != width)
650 				return (0);
651 		} else {
652 			if (font->fontwidth > width)
653 				score -= 10000 + uimin(font->fontwidth - width, 9999);
654 			else
655 				score -= uimin(width - font->fontwidth, 9999);
656 		}
657 	}
658 
659 	if (stride != 0 && font->stride != stride)
660 		return (0);
661 
662 	if (name != NULL && strcmp(font->name, name) != 0)
663 		return (0);
664 
665 	return (score);
666 }
667 
668 int
669 wsfont_find(const char *name, int width, int height, int stride, int bito, int byteo, int flags)
670 {
671 	struct font *ent, *bestent = NULL;
672 	int score, bestscore = 0;
673 
674 	TAILQ_FOREACH(ent, &list, chain) {
675 		score = wsfont_matches(ent->font, name,
676 				width, height, stride, flags);
677 		if (score > bestscore) {
678 			bestscore = score;
679 			bestent = ent;
680 		}
681 	}
682 
683 	if (bestent != NULL)
684 		return (wsfont_make_cookie(bestent->cookie, bito, byteo));
685 
686 	return (-1);
687 }
688 
689 void
690 wsfont_walk(void (*matchfunc)(struct wsdisplay_font *, void *, int), void *cookie)
691 {
692 	struct font *ent;
693 
694 	TAILQ_FOREACH(ent, &list, chain) {
695 		matchfunc(ent->font, cookie, ent->cookie);
696 	}
697 }
698 
699 static struct font *
700 wsfont_add0(struct wsdisplay_font *font, int copy)
701 {
702 	struct font *ent;
703 	size_t size;
704 
705 	ent = malloc(sizeof(struct font), M_DEVBUF, M_WAITOK | M_ZERO);
706 
707 	/* Is this font statically allocated? */
708 	if (!copy) {
709 		ent->font = font;
710 		ent->flags = WSFONT_STATIC;
711 	} else {
712 		void *data;
713 		char *name;
714 
715 		ent->font = malloc(sizeof(struct wsdisplay_font), M_DEVBUF,
716 		    M_WAITOK);
717 		memcpy(ent->font, font, sizeof(*ent->font));
718 
719 		size = font->fontheight * font->numchars * font->stride;
720 		data = malloc(size, M_DEVBUF, M_WAITOK);
721 		memcpy(data, font->data, size);
722 		ent->font->data = data;
723 
724 		name = malloc(strlen(font->name) + 1, M_DEVBUF, M_WAITOK);
725 		strlcpy(name, font->name, strlen(font->name) + 1);
726 		ent->font->name = name;
727 	}
728 
729 	TAILQ_INSERT_TAIL(&list, ent, chain);
730 	return (ent);
731 }
732 
733 int
734 wsfont_add(struct wsdisplay_font *font, int copy)
735 {
736 	struct font *ent;
737 
738 	/* Don't allow exact duplicates */
739 	if (wsfont_find(font->name, font->fontwidth, font->fontheight,
740 	    font->stride, 0, 0, WSFONT_FIND_ALL) >= 0)
741 		return (EEXIST);
742 
743 	ent = wsfont_add0(font, copy);
744 
745 	ident += (1 << WSFONT_IDENT_SHIFT);
746 	ent->cookie = wsfont_make_cookie(ident, font->bitorder,
747 	    font->byteorder);
748 
749 	return (0);
750 }
751 
752 int
753 wsfont_remove(int cookie)
754 {
755 	struct font *ent;
756 
757 	if ((ent = wsfont_find0(cookie, 0xffffffff)) == NULL)
758 		return (ENOENT);
759 
760 	if ((ent->flags & WSFONT_BUILTIN) != 0 || ent->lockcount != 0)
761 		return (EBUSY);
762 
763 	if ((ent->flags & WSFONT_STATIC) == 0) {
764 		free(ent->font->data, M_DEVBUF);
765 		free(__UNCONST(ent->font->name), M_DEVBUF); /*XXXUNCONST*/
766 		free(ent->font, M_DEVBUF);
767 	}
768 
769 	TAILQ_REMOVE(&list, ent, chain);
770 	free(ent, M_DEVBUF);
771 
772 	return (0);
773 }
774 
775 int
776 wsfont_lock(int cookie, struct wsdisplay_font **ptr)
777 {
778 	struct font *ent, *neu;
779 	int bito, byteo;
780 
781 	if ((ent = wsfont_find0(cookie, 0xffffffff)) == NULL) {
782 		if ((ent = wsfont_find0(cookie, WSFONT_IDENT_MASK)) == NULL)
783 			return (ENOENT);
784 
785 		bito = (cookie & WSFONT_BITO_MASK) >> WSFONT_BITO_SHIFT;
786 		byteo = (cookie & WSFONT_BYTEO_MASK) >> WSFONT_BYTEO_SHIFT;
787 
788 		if (ent->lockcount != 0) {
789 			neu = wsfont_add0(ent->font, 1);
790 			neu->flags |= WSFONT_COPY;
791 
792 			aprint_debug("wsfont: font '%s' bito %d byteo %d "
793 			    "copied to bito %d byteo %d\n",
794 			    ent->font->name,
795 			    ent->font->bitorder, ent->font->byteorder,
796 			    bito, byteo);
797 
798 			ent = neu;
799 		}
800 
801 		if (bito && bito != ent->font->bitorder) {
802 			wsfont_revbit(ent->font);
803 			ent->font->bitorder = bito;
804 		}
805 
806 		if (byteo && byteo != ent->font->byteorder) {
807 			wsfont_revbyte(ent->font);
808 			ent->font->byteorder = byteo;
809 		}
810 
811 		ent->cookie = cookie;
812 	}
813 
814 	ent->lockcount++;
815 	*ptr = ent->font;
816 	return (0);
817 }
818 
819 int
820 wsfont_unlock(int cookie)
821 {
822 	struct font *ent;
823 
824 	if ((ent = wsfont_find0(cookie, 0xffffffff)) == NULL)
825 		return (ENOENT);
826 
827 	if (ent->lockcount == 0)
828 		panic("wsfont_unlock: font not locked");
829 
830 	if (--ent->lockcount == 0 && (ent->flags & WSFONT_COPY) != 0)
831 		wsfont_remove(cookie);
832 
833 	return (0);
834 }
835 
836 /*
837  * Unicode to font encoding mappings
838  */
839 
840 /*
841  * To save memory, font encoding tables use a two level lookup.  First the
842  * high byte of the Unicode is used to lookup the level 2 table, then the
843  * low byte indexes that table.  Level 2 tables that are not needed are
844  * omitted (NULL), and both level 1 and level 2 tables have base and size
845  * attributes to keep their size down.
846  */
847 
848 struct wsfont_level1_glyphmap {
849 	const struct	wsfont_level2_glyphmap **level2;
850 	int	base;	/* High byte for first level2 entry	*/
851 	int	size;	/* Number of level2 entries		*/
852 };
853 
854 struct wsfont_level2_glyphmap {
855 	int	base;	/* Low byte for first character		*/
856 	int	size;	/* Number of characters			*/
857 	const void	*chars;	/* Pointer to character number entries  */
858 	int	width;	/* Size of each entry in bytes (1,2,4)  */
859 };
860 
861 #define null16			\
862 	NULL, NULL, NULL, NULL,	\
863 	NULL, NULL, NULL, NULL,	\
864 	NULL, NULL, NULL, NULL,	\
865 	NULL, NULL, NULL, NULL
866 
867 /*
868  * IBM 437 maps
869  */
870 
871 static const u_int8_t ibm437_chars_0[] = {
872 	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
873 	16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
874 	32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
875 	48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
876 	64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
877 	80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
878 	96, 97, 98, 99, 100,101,102,103,104,105,106,107,108,109,110,111,
879 	112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
880 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
881 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
882 	255,173,155,156, 0, 157, 0,  0,  0,  0, 166,174,170, 0,  0,  0,
883 	 0, 241,253, 0,  0,  0,  0, 249, 0,  0, 167,175,172,171, 0, 168,
884 	 0,  0,  0,  0, 142,143,146,128, 0, 144, 0,  0,  0,  0,  0,  0,
885 	 0, 165, 0,  0,  0,  0, 153, 0,  0,  0,  0,  0, 154, 0,  0,  0,
886 	133,160,131, 0, 132,134,145,135,138,130,136,137,141,161,140,139,
887 	 0, 164,149,162,147, 0, 148,246, 0, 151,163,150,129, 0,  0, 152
888 };
889 
890 static const u_int8_t ibm437_chars_1[] = {
891 	159
892 };
893 
894 static const u_int8_t ibm437_chars_3[] = {
895 	226, 0,  0,  0,  0, 233, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
896 	228, 0,  0, 232, 0,  0, 234, 0,  0,  0,  0,  0,  0,  0, 224,225,
897 	 0, 235,238, 0,  0,  0,  0,  0,  0, 230, 0,  0,  0, 227, 0,  0,
898 	229,231
899 };
900 
901 static const u_int8_t ibm437_chars_32[] = {
902 	252, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
903 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
904 	 0,  0,  0,  0,  0,  0,  0,  0, 158
905 };
906 
907 static const u_int8_t ibm437_chars_34[] = {
908 	237, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
909 	 0,  0,  0, 248,250,251, 0,  0,  0, 236, 0,  0,  0,  0,  0,  0,
910 	 0,  0,  0,  0, 239, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
911 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
912 	 0,  0,  0, 247, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
913 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,240,  0,  0,243,
914 	242
915 };
916 
917 static const u_int8_t ibm437_chars_35[] = {
918 	169, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
919 	244,245
920 };
921 
922 static const u_int8_t ibm437_chars_37[] = {
923 	196,205,179,186, 0,  0,  0,  0,  0,  0,  0,  0, 218,213,214,201,
924 	191,184,183,187,192,212,211,200,217,190,189,188,195,198, 0,  0,
925 	199, 0,  0, 204,180,181, 0,  0, 182, 0,  0, 185,194, 0,  0, 209,
926 	210, 0,  0, 203,193, 0,  0, 207,208, 0,  0, 202,197, 0,  0, 216,
927 	 0,  0, 215, 0,  0,  0,  0,  0,  0,  0,  0, 206, 0,  0,  0,  0,
928 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
929 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
930 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
931 	223, 0,  0,  0, 220, 0,  0,  0, 219, 0,  0,  0, 221, 0,  0,  0,
932 	222,176,177,178, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
933 	254
934 };
935 
936 static const struct wsfont_level2_glyphmap ibm437_level2_0 =
937     { 0, 256, ibm437_chars_0, 1 };
938 
939 static const struct wsfont_level2_glyphmap ibm437_level2_1 =
940     { 146, 1, ibm437_chars_1, 1 };
941 
942 static const struct wsfont_level2_glyphmap ibm437_level2_3 =
943     { 147, 50, ibm437_chars_3, 1 };
944 
945 static const struct wsfont_level2_glyphmap ibm437_level2_32 =
946     { 127, 41, ibm437_chars_32, 1 };
947 
948 static const struct wsfont_level2_glyphmap ibm437_level2_34 =
949     { 5, 97, ibm437_chars_34, 1 };
950 
951 static const struct wsfont_level2_glyphmap ibm437_level2_35 =
952     { 16, 18, ibm437_chars_35, 1 };
953 
954 static const struct wsfont_level2_glyphmap ibm437_level2_37 =
955     { 0, 161, ibm437_chars_37, 1 };
956 
957 static const struct wsfont_level2_glyphmap *ibm437_level1[] = {
958 	&ibm437_level2_0, &ibm437_level2_1, NULL, &ibm437_level2_3,
959 	NULL, NULL, NULL, NULL,
960 	NULL, NULL, NULL, NULL,
961 	NULL, NULL, NULL, NULL,
962 	NULL, NULL, NULL, NULL,
963 	NULL, NULL, NULL, NULL,
964 	NULL, NULL, NULL, NULL,
965 	NULL, NULL, NULL, NULL,
966 	&ibm437_level2_32, NULL, &ibm437_level2_34, &ibm437_level2_35,
967 	NULL, &ibm437_level2_37
968 };
969 
970 /*
971  * ISO-8859-7 maps
972  */
973 static const u_int8_t iso7_chars_0[] = {
974 	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
975 	16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
976 	32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
977 	48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
978 	64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
979 	80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
980 	96, 97, 98, 99, 100,101,102,103,104,105,106,107,108,109,110,111,
981 	112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
982 	128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
983 	144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
984 	160, 0,  0, 163, 0,  0, 166,167,168,169, 0, 171,172,173, 0,  0,
985 	176,177,178,179,180, 0,  0, 183, 0,  0,  0, 187, 0, 189
986 };
987 
988 static const u_int8_t iso7_chars_3[] = {
989 	182, 0, 184,185,186, 0, 188, 0, 190,191,192,193,194,195,196,197,
990 	198,199,200,201,202,203,204,205,206,207,208,209, 0, 211,212,213,
991 	214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,
992 	230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,
993 	246,247,248,249,250,251,252,253,254, 0,  0,  0,  0,  0,  0,  0,
994 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
995 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 181
996 };
997 
998 /*
999  * map all variants of the box drawing characters to the same basic shapes for
1000  * now, encoded like this:
1001  *
1002  *    1
1003  *    1
1004  * 888 222
1005  *    4
1006  *    4
1007  *
1008  * so an upright line would be 0x05
1009  */
1010 #define FL |WSFONT_FLAG_OPT
1011 static const u_int32_t netbsd_boxes[] = {
1012 /*00*/ 0x0a FL, 0x0a FL, 0x05 FL, 0x05 FL, 0x0a FL, 0x0a FL, 0x05 FL, 0x05 FL,
1013 /*08*/ 0x0a FL, 0x0a FL, 0x05 FL, 0x05 FL, 0x06 FL, 0x06 FL, 0x06 FL, 0x06 FL,
1014 /*10*/ 0x0c FL, 0x0c FL, 0x0c FL, 0x0c FL, 0x03 FL, 0x03 FL, 0x03 FL, 0x03 FL,
1015 /*18*/ 0x09 FL, 0x09 FL, 0x09 FL, 0x09 FL, 0x07 FL, 0x07 FL, 0x07 FL, 0x07 FL,
1016 /*20*/ 0x07 FL, 0x07 FL, 0x07 FL, 0x07 FL, 0x0d FL, 0x0d FL, 0x0d FL, 0x0d FL,
1017 /*28*/ 0x0d FL, 0x0d FL, 0x0d FL, 0x0d FL, 0x0e FL, 0x0e FL, 0x0e FL, 0x0e FL,
1018 /*30*/ 0x0e FL, 0x0e FL, 0x0e FL, 0x0e FL, 0x0b FL, 0x0b FL, 0x0b FL, 0x0b FL,
1019 /*38*/ 0x0b FL, 0x0b FL, 0x0b FL, 0x0b FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL,
1020 /*40*/ 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL,
1021 /*48*/ 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0a FL, 0x0a FL, 0x05 FL, 0x05 FL,
1022 /*50*/ 0x0a FL, 0x05 FL, 0x06 FL, 0x06 FL, 0x06 FL, 0x0c FL, 0x0c FL, 0x0c FL,
1023 /*58*/ 0x03 FL, 0x03 FL, 0x03 FL, 0x09 FL, 0x09 FL, 0x09 FL, 0x07 FL, 0x07 FL,
1024 /*60*/ 0x07 FL, 0x0d FL, 0x0d FL, 0x0d FL, 0x0e FL, 0x0e FL, 0x0e FL, 0x0b FL,
1025 /*68*/ 0x0b FL, 0x0b FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x06 FL, 0x0c FL, 0x09 FL,
1026 /*70*/ 0x03 FL,    0 FL,    0 FL,    0 FL, 0x08 FL, 0x01 FL, 0x02 FL, 0x04 FL,
1027 /*78*/ 0x08 FL, 0x01 FL, 0x02 FL, 0x04 FL, 0x0a FL, 0x05 FL, 0x0a FL, 0x05 FL
1028 };
1029 #undef FL
1030 
1031 static const u_int8_t iso7_chars_32[] = {
1032 	175, 0,  0,  0,  0, 162, 0, 161
1033 };
1034 
1035 static const struct wsfont_level2_glyphmap iso7_level2_0 =
1036     { 0, 190, iso7_chars_0, 1 };
1037 
1038 static const struct wsfont_level2_glyphmap iso7_level2_3 =
1039     { 134, 111, iso7_chars_3, 1 };
1040 
1041 static const struct wsfont_level2_glyphmap iso7_level2_32 =
1042     { 20, 8, iso7_chars_32, 1 };
1043 
1044 static const struct wsfont_level2_glyphmap netbsd_box_drawing =
1045     { 0, 128, netbsd_boxes, 4 };
1046 
1047 static const struct wsfont_level2_glyphmap *iso7_level1[] = {
1048 	&iso7_level2_0, NULL, NULL, &iso7_level2_3,
1049 	NULL, NULL, NULL, NULL,
1050 	NULL, NULL, NULL, NULL,
1051 	NULL, NULL, NULL, NULL,
1052 	NULL, NULL, NULL, NULL,
1053 	NULL, NULL, NULL, NULL,
1054 	NULL, NULL, NULL, NULL,
1055 	NULL, NULL, NULL, NULL,
1056 	&iso7_level2_32, NULL, NULL, NULL,
1057 	NULL, &netbsd_box_drawing
1058 };
1059 
1060 static const struct wsfont_level2_glyphmap *iso_level1[] = {
1061 	NULL, NULL, NULL, NULL,
1062 	NULL, NULL, NULL, NULL,
1063 	NULL, NULL, NULL, NULL,
1064 	NULL, NULL, NULL, NULL,
1065 	NULL, NULL, NULL, NULL,
1066 	NULL, NULL, NULL, NULL,
1067 	NULL, NULL, NULL, NULL,
1068 	NULL, NULL, NULL, NULL,
1069 	NULL, NULL, NULL, NULL,
1070 	NULL, &netbsd_box_drawing
1071 };
1072 
1073 static const struct wsfont_level1_glyphmap encodings[] = {
1074 	{ iso_level1, 0, 0x26 },	/* WSDISPLAY_FONTENC_ISO */
1075 	{ ibm437_level1, 0, 38 },	/* WSDISPLAY_FONTENC_IBM */
1076 	{ NULL, 0, 0 },			/* WSDISPLAY_FONTENC_PCVT */
1077 	{ iso7_level1, 0, 0x26 },	/* WSDISPLAY_FONTENC_ISO7 */
1078 };
1079 
1080 #define MAX_ENCODING (sizeof(encodings) / sizeof(encodings[0]))
1081 
1082 /*
1083  * Remap Unicode character to glyph
1084  */
1085 int
1086 wsfont_map_unichar(struct wsdisplay_font *font, int c)
1087 {
1088 	const struct wsfont_level1_glyphmap *map1;
1089 	const struct wsfont_level2_glyphmap *map2;
1090 	int hi, lo;
1091 
1092 	if (font->encoding < 0 || font->encoding >= MAX_ENCODING)
1093 		return (-1);
1094 
1095 	hi = (c >> 8);
1096 	lo = c & 255;
1097 	map1 = &encodings[font->encoding];
1098 
1099 	if (hi < map1->base || hi >= map1->base + map1->size)
1100 		return (-1);
1101 
1102 	map2 = map1->level2[hi - map1->base];
1103 
1104 	/* so we don't need an identical level 2 table for hi == 0 */
1105 	if (hi == 0 && font->encoding == WSDISPLAY_FONTENC_ISO)
1106 		return lo;
1107 
1108 	if (map2 == NULL || lo < map2->base || lo >= map2->base + map2->size)
1109 		return (-1);
1110 
1111 	lo -= map2->base;
1112 
1113 	switch(map2->width) {
1114 	case 1:
1115 		c = (((const u_int8_t *)map2->chars)[lo]);
1116 		break;
1117 	case 2:
1118 		c = (((const u_int16_t *)map2->chars)[lo]);
1119 		break;
1120 	case 4:
1121 		c = (((const u_int32_t *)map2->chars)[lo]);
1122 		break;
1123 	}
1124 
1125 	if (c == 0 && lo != 0)
1126 		return (-1);
1127 
1128 	return (c);
1129 }
1130