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