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