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