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