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