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