xref: /openbsd-src/sys/dev/wsfont/wsfont.c (revision 99fd087599a8791921855f21bd7e36130f39aadc)
1 /*	$OpenBSD: wsfont.c,v 1.56 2019/07/11 18:07:54 mpi Exp $ */
2 /*	$NetBSD: wsfont.c,v 1.17 2001/02/07 13:59:24 ad Exp $	*/
3 
4 /*-
5  * Copyright (c) 1999 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Andrew Doran.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/time.h>
36 #include <sys/malloc.h>
37 #include <sys/queue.h>
38 
39 #include <dev/wscons/wsconsio.h>
40 #include <dev/wsfont/wsfont.h>
41 
42 #include "wsfont_glue.h"	/* NRASOPS_ROTATION */
43 
44 #undef HAVE_FONT
45 
46 #ifdef FONT_SPLEEN5x8
47 #define HAVE_FONT 1
48 #include <dev/wsfont/spleen5x8.h>
49 #endif
50 
51 #ifdef FONT_SPLEEN8x16
52 #define HAVE_FONT 1
53 #endif
54 
55 #ifdef FONT_SPLEEN12x24
56 #define HAVE_FONT 1
57 #endif
58 
59 #ifdef FONT_SPLEEN16x32
60 #define HAVE_FONT 1
61 #endif
62 
63 #ifdef FONT_SPLEEN32x64
64 #define HAVE_FONT 1
65 #endif
66 
67 #ifdef FONT_BOLD8x16
68 #define HAVE_FONT 1
69 #include <dev/wsfont/bold8x16.h>
70 #endif
71 
72 #ifdef FONT_GALLANT12x22
73 #define HAVE_FONT 1
74 #endif
75 
76 #ifdef FONT_BOLD8x16_ISO1
77 #define HAVE_FONT 1
78 #include <dev/wsfont/bold8x16-iso1.h>
79 #endif
80 
81 /*
82  * Make sure we always have at least one font.
83  * Unless otherwise configured, all platforms provide both a 8x16 font and a
84  * larger 12x22 font.
85  * Some platforms will however only provide the 8x16 font if option
86  * SMALL_KERNEL.
87  */
88 #ifndef HAVE_FONT
89 #define HAVE_FONT 1
90 
91 #define	FONT_SPLEEN8x16
92 #if defined(__sparc64__)
93 #define	FONT_GALLANT12x22
94 #elif defined(__alpha__) || defined(__luna88k__) || defined(__macppc__) || \
95     defined(__sgi__) || !defined(SMALL_KERNEL)
96 #define FONT_SPLEEN12x24
97 #endif
98 
99 #if !defined(SMALL_KERNEL) && (defined(__amd64__) || defined(__i386__) || \
100     defined(__arm64__))
101 #define FONT_SPLEEN16x32
102 #define FONT_SPLEEN32x64
103 #endif
104 
105 #endif	/* HAVE_FONT */
106 
107 #ifdef FONT_GALLANT12x22
108 #include <dev/wsfont/gallant12x22.h>
109 #endif
110 
111 #ifdef FONT_SPLEEN8x16
112 #include <dev/wsfont/spleen8x16.h>
113 #endif
114 
115 #ifdef FONT_SPLEEN12x24
116 #include <dev/wsfont/spleen12x24.h>
117 #endif
118 
119 #ifdef FONT_SPLEEN16x32
120 #include <dev/wsfont/spleen16x32.h>
121 #endif
122 
123 #ifdef FONT_SPLEEN32x64
124 #include <dev/wsfont/spleen32x64.h>
125 #endif
126 
127 struct font {
128 	TAILQ_ENTRY(font) chain;
129 	struct	wsdisplay_font *font;
130 	u_short	lockcount;
131 	u_short	cookie;
132 	u_short	flg;
133 };
134 TAILQ_HEAD(, font) fontlist;
135 
136 /* Our list of built-in fonts */
137 static struct font builtin_fonts[] = {
138 #define BUILTIN_FONT(f, c) \
139 	{ .font = &(f), .cookie = (c), .lockcount = 0, \
140 	  .flg = WSFONT_STATIC | WSFONT_BUILTIN }
141 #ifdef FONT_BOLD8x16
142 	BUILTIN_FONT(bold8x16, 1),
143 #endif
144 #ifdef FONT_BOLD8x16_ISO1
145 	BUILTIN_FONT(bold8x16_iso1, 2),
146 #endif
147 #ifdef FONT_GALLANT12x22
148 	BUILTIN_FONT(gallant12x22, 3),
149 #endif
150 #ifdef FONT_SPLEEN5x8
151 	BUILTIN_FONT(spleen5x8, 4),
152 #endif
153 #ifdef FONT_SPLEEN8x16
154 	BUILTIN_FONT(spleen8x16, 5),
155 #endif
156 #ifdef FONT_SPLEEN12x24
157 	BUILTIN_FONT(spleen12x24, 6),
158 #endif
159 #ifdef FONT_SPLEEN16x32
160 	BUILTIN_FONT(spleen16x32, 7),
161 #endif
162 #ifdef FONT_SPLEEN32x64
163 	BUILTIN_FONT(spleen32x64, 8),
164 #endif
165 #undef BUILTIN_FONT
166 };
167 
168 #if !defined(SMALL_KERNEL) || defined(__alpha__)
169 #define INCLUDE_FONT_BIT_ENDIANNESS_SWAP_CODE
170 #endif
171 
172 #ifdef INCLUDE_FONT_BIT_ENDIANNESS_SWAP_CODE
173 
174 /* Reverse the bit order in a byte */
175 static const u_char reverse[256] = {
176 	0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
177 	0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
178 	0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
179 	0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
180 	0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
181 	0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
182 	0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
183 	0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
184 	0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
185 	0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
186 	0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
187 	0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
188 	0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
189 	0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
190 	0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
191 	0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
192 	0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
193 	0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
194 	0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
195 	0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
196 	0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
197 	0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
198 	0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
199 	0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
200 	0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
201 	0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
202 	0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
203 	0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
204 	0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
205 	0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
206 	0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
207 	0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
208 };
209 
210 #endif
211 
212 static struct font *wsfont_find0(int);
213 
214 #ifdef INCLUDE_FONT_BIT_ENDIANNESS_SWAP_CODE
215 
216 /*
217  * Reverse the bit order of a font
218  */
219 static void	wsfont_revbit(struct wsdisplay_font *);
220 static void
221 wsfont_revbit(struct wsdisplay_font *font)
222 {
223 	u_char *p, *m;
224 
225 	p = (u_char *)font->data;
226 	m = p + font->stride * font->numchars * font->fontheight;
227 
228 	for (; p < m; p++)
229 		*p = reverse[*p];
230 }
231 
232 #endif
233 
234 #if !defined(SMALL_KERNEL)
235 
236 /*
237  * Reverse the byte order of a font
238  */
239 static void	wsfont_revbyte(struct wsdisplay_font *);
240 static void
241 wsfont_revbyte(struct wsdisplay_font *font)
242 {
243 	int x, l, r, nr;
244 	u_char *rp;
245 
246 	if (font->stride == 1)
247 		return;
248 
249 	rp = (u_char *)font->data;
250 	nr = font->numchars * font->fontheight;
251 
252 	while (nr--) {
253 		l = 0;
254 		r = font->stride - 1;
255 
256 		while (l < r) {
257 			x = rp[l];
258 			rp[l] = rp[r];
259 			rp[r] = x;
260 			l++, r--;
261 		}
262 
263 		rp += font->stride;
264 	}
265 }
266 
267 #endif
268 
269 /*
270  * Enumerate the list of fonts
271  */
272 void
273 wsfont_enum(int (*cb)(void *, struct wsdisplay_font *), void *cbarg)
274 {
275 	struct font *ent;
276 	int s;
277 
278 	s = splhigh();
279 
280 	TAILQ_FOREACH(ent, &fontlist, chain)
281 		if (cb(cbarg, ent->font) != 0)
282 			break;
283 
284 	splx(s);
285 }
286 
287 #if NRASOPS_ROTATION > 0
288 
289 void wsfont_rotate_cw(struct wsdisplay_font *, char *, int);
290 void wsfont_rotate_ccw(struct wsdisplay_font *, char *, int);
291 struct wsdisplay_font *wsfont_rotate_internal(struct wsdisplay_font *, int);
292 
293 void
294 wsfont_rotate_cw(struct wsdisplay_font *font, char *newbits, int newstride)
295 {
296 	int b, n, r;
297 
298 	/* Rotate the font a bit at a time. */
299 	for (n = 0; n < font->numchars; n++) {
300 		char *ch = font->data + (n * font->stride * font->fontheight);
301 
302 		for (r = 0; r < font->fontheight; r++) {
303 			for (b = 0; b < font->fontwidth; b++) {
304 				unsigned char *rb;
305 
306 				rb = ch + (font->stride * r) + (b / 8);
307 				if (*rb & (0x80 >> (b % 8))) {
308 					unsigned char *rrb;
309 
310 					rrb = newbits + newstride - 1 - (r / 8)
311 					    + (n * newstride * font->fontwidth)
312 					    + (newstride * b);
313 					*rrb |= (1 << (r % 8));
314 				}
315 			}
316 		}
317 	}
318 }
319 
320 void
321 wsfont_rotate_ccw(struct wsdisplay_font *font, char *newbits, int newstride)
322 {
323 	int b, n, r;
324 
325 	/* Rotate the font a bit at a time. */
326 	for (n = 0; n < font->numchars; n++) {
327 		char *ch = font->data + (n * font->stride * font->fontheight);
328 
329 		for (r = 0; r < font->fontheight; r++) {
330 			for (b = 0; b < font->fontwidth; b++) {
331 				int bb = font->fontwidth - 1 - b;
332 				unsigned char *rb;
333 
334 				rb = ch + (font->stride * r) + (b / 8);
335 				if (*rb & (0x80 >> (b % 8))) {
336 					unsigned char *rrb;
337 
338 					rrb = newbits + (r / 8)
339 					    + (n * newstride * font->fontwidth)
340 					    + (newstride * bb);
341 					*rrb |= (1 << (7 - (r % 8)));
342 				}
343 			}
344 		}
345 	}
346 }
347 
348 struct wsdisplay_font *
349 wsfont_rotate_internal(struct wsdisplay_font *font, int ccw)
350 {
351 	int newstride;
352 	struct wsdisplay_font *newfont;
353 	char *newbits;
354 
355 	/* Duplicate the existing font... */
356 	newfont = malloc(sizeof *font, M_DEVBUF, M_WAITOK);
357 
358 	bcopy(font, newfont, sizeof *font);
359 	newfont->cookie = NULL;
360 
361 	/* Allocate a buffer big enough for the rotated font. */
362 	newstride = (font->fontheight + 7) / 8;
363 	newbits = mallocarray(font->numchars, newstride * font->fontwidth,
364 	    M_DEVBUF, M_WAITOK | M_ZERO);
365 
366 	if (ccw)
367 		wsfont_rotate_ccw(font, newbits, newstride);
368 	else
369 		wsfont_rotate_cw(font, newbits, newstride);
370 
371 	newfont->data = newbits;
372 
373 	/* Update font sizes. */
374 	newfont->stride = newstride;
375 	newfont->fontwidth = font->fontheight;
376 	newfont->fontheight = font->fontwidth;
377 
378 	if (wsfont_add(newfont, 0) != 0) {
379 		/*
380 		 * If we seem to have rotated this font already, drop the
381 		 * new one...
382 		 */
383 		free(newbits, M_DEVBUF,
384 		    font->numchars * newstride * font->fontwidth);
385 		free(newfont, M_DEVBUF, sizeof *font);
386 		newfont = NULL;
387 	}
388 
389 	return (newfont);
390 }
391 
392 int
393 wsfont_rotate(int cookie, int ccw)
394 {
395 	int s, ncookie;
396 	struct wsdisplay_font *font;
397 	struct font *origfont;
398 
399 	s = splhigh();
400 	origfont = wsfont_find0(cookie);
401 	splx(s);
402 
403 	font = wsfont_rotate_internal(origfont->font, ccw);
404 	if (font == NULL)
405 		return (-1);
406 
407 	ncookie = wsfont_find(font->name, font->fontwidth, font->fontheight,
408 	    font->stride);
409 
410 	return (ncookie);
411 }
412 
413 #endif	/* NRASOPS_ROTATION */
414 
415 /*
416  * Initialize list with WSFONT_BUILTIN fonts
417  */
418 void
419 wsfont_init(void)
420 {
421 	static int again;
422 	unsigned int i;
423 
424 	if (again != 0)
425 		return;
426 	again = 1;
427 
428 	TAILQ_INIT(&fontlist);
429 
430 	for (i = 0; i < nitems(builtin_fonts); i++) {
431 		TAILQ_INSERT_TAIL(&fontlist, &builtin_fonts[i], chain);
432 	}
433 }
434 
435 /*
436  * Find a font by cookie. Called at splhigh.
437  */
438 static struct font *
439 wsfont_find0(int cookie)
440 {
441 	struct font *ent;
442 
443 	TAILQ_FOREACH(ent, &fontlist, chain)
444 		if (ent->cookie == cookie)
445 			return (ent);
446 
447 	return (NULL);
448 }
449 
450 /*
451  * Find a font.
452  */
453 int
454 wsfont_find(const char *name, int width, int height, int stride)
455 {
456 	struct font *ent;
457 	int s;
458 
459 	s = splhigh();
460 
461 	TAILQ_FOREACH(ent, &fontlist, chain) {
462 		if (height != 0 && ent->font->fontheight != height)
463 			continue;
464 
465 		if (width != 0 && ent->font->fontwidth != width)
466 			continue;
467 
468 		if (stride != 0 && ent->font->stride != stride)
469 			continue;
470 
471 		if (name != NULL && strcmp(ent->font->name, name) != 0)
472 			continue;
473 
474 		splx(s);
475 		return (ent->cookie);
476 	}
477 
478 	splx(s);
479 	return (-1);
480 }
481 
482 /*
483  * Add a font to the list.
484  */
485 int
486 wsfont_add(struct wsdisplay_font *font, int copy)
487 {
488 	static int cookiegen = 666;
489 	struct font *ent;
490 	int s, fontc = 0;
491 
492 	s = splhigh();
493 
494 	/* Don't allow exact duplicates */
495 	if (wsfont_find(font->name, font->fontwidth, font->fontheight,
496 	    font->stride) >= 0) {
497 		splx(s);
498 		return (-1);
499 	}
500 
501 	TAILQ_FOREACH(ent, &fontlist, chain)
502 		fontc++;
503 
504 	if (fontc >= WSDISPLAY_MAXFONTCOUNT) {
505 		splx(s);
506 		return (-1);
507 	}
508 
509 	ent = (struct font *)malloc(sizeof *ent, M_DEVBUF, M_WAITOK);
510 
511 	ent->lockcount = 0;
512 	ent->flg = 0;
513 	ent->cookie = cookiegen++;
514 
515 	/*
516 	 * If we are coming from a WSDISPLAYIO_LDFONT ioctl, we need to
517 	 * make a copy of the wsdisplay_font struct, but not of font->bits.
518 	 */
519 	if (copy) {
520 		ent->font = (struct wsdisplay_font *)malloc(sizeof *ent->font,
521 		    M_DEVBUF, M_WAITOK);
522 		memcpy(ent->font, font, sizeof(*ent->font));
523 		ent->flg = 0;
524 	} else {
525 		ent->font = font;
526 		ent->flg = WSFONT_STATIC;
527 	}
528 
529 	/* Now link into the list and return */
530 	TAILQ_INSERT_TAIL(&fontlist, ent, chain);
531 	splx(s);
532 	return (0);
533 }
534 
535 /*
536  * Lock a given font and return new lockcount. This fails if the cookie
537  * is invalid, or if the font is already locked and the bit/byte order
538  * requested by the caller differs.
539  */
540 int
541 wsfont_lock(int cookie, struct wsdisplay_font **ptr, int bitorder,
542     int byteorder)
543 {
544 	struct font *ent;
545 	int s, lc;
546 
547 	s = splhigh();
548 
549 	if ((ent = wsfont_find0(cookie)) != NULL) {
550 		if (bitorder && bitorder != ent->font->bitorder) {
551 #ifdef INCLUDE_FONT_BIT_ENDIANNESS_SWAP_CODE
552 			if (ent->lockcount) {
553 				splx(s);
554 				return (-1);
555 			}
556 			wsfont_revbit(ent->font);
557 			ent->font->bitorder = bitorder;
558 #else
559 			splx(s);
560 			return (-1);
561 #endif
562 		}
563 
564 		if (byteorder && byteorder != ent->font->byteorder) {
565 #if !defined(SMALL_KERNEL)
566 			if (ent->lockcount) {
567 				splx(s);
568 				return (-1);
569 			}
570 			wsfont_revbyte(ent->font);
571 			ent->font->byteorder = byteorder;
572 #else
573 			splx(s);
574 			return (-1);
575 #endif
576 		}
577 
578 		lc = ++ent->lockcount;
579 		*ptr = ent->font;
580 	} else
581 		lc = -1;
582 
583 	splx(s);
584 	return (lc);
585 }
586 
587 /*
588  * Unlock a given font and return new lockcount.
589  */
590 int
591 wsfont_unlock(int cookie)
592 {
593 	struct font *ent;
594 	int s, lc;
595 
596 	s = splhigh();
597 
598 	if ((ent = wsfont_find0(cookie)) != NULL) {
599 		if (ent->lockcount == 0)
600 			panic("wsfont_unlock: font not locked");
601 		lc = --ent->lockcount;
602 	} else
603 		lc = -1;
604 
605 	splx(s);
606 	return (lc);
607 }
608 
609 #if !defined(SMALL_KERNEL)
610 
611 /*
612  * Unicode to font encoding mappings
613  */
614 
615 /*
616  * To save memory, font encoding tables use a two level lookup.
617  * First the high byte of the Unicode is used to lookup the level 2
618  * table, then the low byte indexes that table.  Level 2 tables that are
619  * not needed are omitted (NULL), and both level 1 and level 2 tables
620  * have base and size attributes to keep their size down.
621  */
622 
623 struct wsfont_level1_glyphmap {
624 	struct wsfont_level2_glyphmap **level2;
625 	int base;	/* High byte for first level2 entry	*/
626 	int size;	/* Number of level2 entries		*/
627 };
628 
629 struct wsfont_level2_glyphmap {
630 	int base;	/* Low byte for first character		*/
631 	int size;	/* Number of characters			*/
632 	void *chars;	/* Pointer to character number entries  */
633 	int width;	/* Size of each entry in bytes (1,2,4)  */
634 };
635 
636 /*
637  * IBM 437 maps
638  */
639 
640 static u_int8_t
641 ibm437_chars_0[] = {
642 	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
643 	16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
644 	32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
645 	48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
646 	64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
647 	80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
648 	96, 97, 98, 99, 100,101,102,103,104,105,106,107,108,109,110,111,
649 	112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
650 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
651 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
652 	255,173,155,156, 0, 157, 0,  0,  0,  0, 166,174,170, 0,  0,  0,
653 	 0, 241,253, 0,  0,  0,  0, 249, 0,  0, 167,175,172,171, 0, 168,
654 	 0,  0,  0,  0, 142,143,146,128, 0, 144, 0,  0,  0,  0,  0,  0,
655 	 0, 165, 0,  0,  0,  0, 153, 0,  0,  0,  0,  0, 154, 0,  0,  0,
656 	133,160,131, 0, 132,134,145,135,138,130,136,137,141,161,140,139,
657 	 0, 164,149,162,147, 0, 148,246, 0, 151,163,150,129, 0,  0, 152
658 },
659 ibm437_chars_1[] = {
660 	159
661 },
662 ibm437_chars_3[] = {
663 	226, 0,  0,  0,  0, 233, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
664 	228, 0,  0, 232, 0,  0, 234, 0,  0,  0,  0,  0,  0,  0, 224,225,
665 	 0, 235,238, 0,  0,  0,  0,  0,  0, 230, 0,  0,  0, 227, 0,  0,
666 	229,231
667 },
668 ibm437_chars_32[] = {
669 	252, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
670 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
671 	 0,  0,  0,  0,  0,  0,  0,  0, 158
672 },
673 ibm437_chars_34[] = {
674 	237, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
675 	 0,  0,  0, 248,250,251, 0,  0,  0, 236, 0,  0,  0,  0,  0,  0,
676 	 0,  0,  0,  0, 239, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
677 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
678 	 0,  0,  0, 247, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
679 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,240,  0,  0,243,
680 	242
681 },
682 ibm437_chars_35[] = {
683 	169, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
684 	244,245
685 },
686 ibm437_chars_37[] = {
687 	196,205,179,186, 0,  0,  0,  0,  0,  0,  0,  0, 218,213,214,201,
688 	191,184,183,187,192,212,211,200,217,190,189,188,195,198, 0,  0,
689 	199, 0,  0, 204,180,181, 0,  0, 182, 0,  0, 185,194, 0,  0, 209,
690 	210, 0,  0, 203,193, 0,  0, 207,208, 0,  0, 202,197, 0,  0, 216,
691 	 0,  0, 215, 0,  0,  0,  0,  0,  0,  0,  0, 206, 0,  0,  0,  0,
692 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
693 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
694 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
695 	223, 0,  0,  0, 220, 0,  0,  0, 219, 0,  0,  0, 221, 0,  0,  0,
696 	222,176,177,178, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
697 	254
698 };
699 
700 static struct wsfont_level2_glyphmap
701 ibm437_level2_0 = { 0, 256, ibm437_chars_0, 1 },
702 ibm437_level2_1 = { 146, 1, ibm437_chars_1, 1 },
703 ibm437_level2_3 = { 147, 50, ibm437_chars_3, 1 },
704 ibm437_level2_32 = { 127, 41, ibm437_chars_32, 1 },
705 ibm437_level2_34 = { 5, 97, ibm437_chars_34, 1 },
706 ibm437_level2_35 = { 16, 18, ibm437_chars_35, 1 },
707 ibm437_level2_37 = { 0, 161, ibm437_chars_37, 1 };
708 
709 static struct wsfont_level2_glyphmap *ibm437_level1[] = {
710 	&ibm437_level2_0, &ibm437_level2_1, NULL, &ibm437_level2_3,
711 	NULL, NULL, NULL, NULL,
712 	NULL, NULL, NULL, NULL,
713 	NULL, NULL, NULL, NULL,
714 	NULL, NULL, NULL, NULL,
715 	NULL, NULL, NULL, NULL,
716 	NULL, NULL, NULL, NULL,
717 	NULL, NULL, NULL, NULL,
718 	&ibm437_level2_32, NULL, &ibm437_level2_34, &ibm437_level2_35,
719 	NULL, &ibm437_level2_37
720 };
721 
722 static struct wsfont_level1_glyphmap encodings[] = {
723 	/* WSDISPLAY_FONTENC_ISO */
724 	{ NULL, 0, 0 },
725 	/* WSDISPLAY_FONTENC_IBM */
726 	{ ibm437_level1, 0, nitems(ibm437_level1) }
727 };
728 
729 #endif	/* !SMALL_KERNEL */
730 
731 /*
732  * Remap Unicode character to glyph
733  */
734 int
735 wsfont_map_unichar(struct wsdisplay_font *font, int c)
736 {
737 	if (font->encoding == WSDISPLAY_FONTENC_ISO)
738 		return (c);
739 
740 #if !defined(SMALL_KERNEL)
741 	if (font->encoding >= 0 && font->encoding < nitems(encodings)) {
742 		int hi = (c >> 8), lo = c & 255;
743 		struct wsfont_level1_glyphmap *map1 =
744 		    &encodings[font->encoding];
745 		struct wsfont_level2_glyphmap *map2;
746 
747 		hi -= map1->base;
748 
749 		if (hi >= 0 && hi < map1->size &&
750 		    (map2 = map1->level2[hi]) != NULL) {
751 			lo -= map2->base;
752 
753 			if (lo >= 0 && lo < map2->size) {
754 				switch (map2->width) {
755 				case 1:
756 					c = (((u_int8_t *)map2->chars)[lo]);
757 					break;
758 				case 2:
759 					c = (((u_int16_t *)map2->chars)[lo]);
760 					break;
761 				case 4:
762 					c = (((u_int32_t *)map2->chars)[lo]);
763 					break;
764 				}
765 
766 				if (c != 0 || lo == 0)
767 					return (c);
768 			}
769 		}
770 	}
771 #endif	/* !SMALL_KERNEL */
772 
773 	return (-1);
774 }
775