xref: /openbsd-src/sys/dev/wsfont/wsfont.c (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1 /*	$OpenBSD: wsfont.c,v 1.44 2016/09/14 03:25:51 jcs 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(__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, fontc = 0;
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 	TAILQ_FOREACH(ent, &fontlist, chain)
465 		fontc++;
466 
467 	if (fontc >= WSDISPLAY_MAXFONTCOUNT) {
468 		splx(s);
469 		return (-1);
470 	}
471 
472 	ent = (struct font *)malloc(sizeof *ent, M_DEVBUF, M_WAITOK);
473 
474 	ent->lockcount = 0;
475 	ent->flg = 0;
476 	ent->cookie = cookiegen++;
477 
478 	/*
479 	 * If we are coming from a WSDISPLAYIO_LDFONT ioctl, we need to
480 	 * make a copy of the wsdisplay_font struct, but not of font->bits.
481 	 */
482 	if (copy) {
483 		ent->font = (struct wsdisplay_font *)malloc(sizeof *ent->font,
484 		    M_DEVBUF, M_WAITOK);
485 		memcpy(ent->font, font, sizeof(*ent->font));
486 		ent->flg = 0;
487 	} else {
488 		ent->font = font;
489 		ent->flg = WSFONT_STATIC;
490 	}
491 
492 	/* Now link into the list and return */
493 	TAILQ_INSERT_TAIL(&fontlist, ent, chain);
494 	splx(s);
495 	return (0);
496 }
497 
498 /*
499  * Remove a font.
500  */
501 #ifdef notyet
502 int
503 wsfont_remove(int cookie)
504 {
505 	struct font *ent;
506 	int s;
507 
508 	s = splhigh();
509 
510 	if ((ent = wsfont_find0(cookie)) == NULL) {
511 		splx(s);
512 		return (-1);
513 	}
514 
515 	if ((ent->flg & WSFONT_BUILTIN) != 0 || ent->lockcount != 0) {
516 		splx(s);
517 		return (-1);
518 	}
519 
520 	/* Don't free statically allocated font data */
521 	if ((ent->flg & WSFONT_STATIC) != 0) {
522 		free(ent->font->data, M_DEVBUF, 0);
523 		free(ent->font, M_DEVBUF, 0);
524 	}
525 
526 	/* Remove from list, free entry */
527 	TAILQ_REMOVE(&list, ent, chain);
528 	free(ent, M_DEVBUF, 0);
529 	splx(s);
530 	return (0);
531 }
532 #endif
533 
534 /*
535  * Lock a given font and return new lockcount. This fails if the cookie
536  * is invalid, or if the font is already locked and the bit/byte order
537  * requested by the caller differs.
538  */
539 int
540 wsfont_lock(int cookie, struct wsdisplay_font **ptr, int bitorder,
541     int byteorder)
542 {
543 	struct font *ent;
544 	int s, lc;
545 
546 	s = splhigh();
547 
548 	if ((ent = wsfont_find0(cookie)) != NULL) {
549 		if (bitorder && bitorder != ent->font->bitorder) {
550 #ifdef INCLUDE_FONT_BIT_ENDIANNESS_SWAP_CODE
551 			if (ent->lockcount) {
552 				splx(s);
553 				return (-1);
554 			}
555 			wsfont_revbit(ent->font);
556 			ent->font->bitorder = bitorder;
557 #else
558 			splx(s);
559 			return (-1);
560 #endif
561 		}
562 
563 		if (byteorder && byteorder != ent->font->byteorder) {
564 #if !defined(SMALL_KERNEL)
565 			if (ent->lockcount) {
566 				splx(s);
567 				return (-1);
568 			}
569 			wsfont_revbyte(ent->font);
570 			ent->font->byteorder = byteorder;
571 #else
572 			splx(s);
573 			return (-1);
574 #endif
575 		}
576 
577 		lc = ++ent->lockcount;
578 		*ptr = ent->font;
579 	} else
580 		lc = -1;
581 
582 	splx(s);
583 	return (lc);
584 }
585 
586 /*
587  * Unlock a given font and return new lockcount.
588  */
589 int
590 wsfont_unlock(int cookie)
591 {
592 	struct font *ent;
593 	int s, lc;
594 
595 	s = splhigh();
596 
597 	if ((ent = wsfont_find0(cookie)) != NULL) {
598 		if (ent->lockcount == 0)
599 			panic("wsfont_unlock: font not locked");
600 		lc = --ent->lockcount;
601 	} else
602 		lc = -1;
603 
604 	splx(s);
605 	return (lc);
606 }
607 
608 #if !defined(SMALL_KERNEL)
609 
610 /*
611  * Unicode to font encoding mappings
612  */
613 
614 /*
615  * To save memory, font encoding tables use a two level lookup.
616  * First the high byte of the Unicode is used to lookup the level 2
617  * table, then the low byte indexes that table.  Level 2 tables that are
618  * not needed are omitted (NULL), and both level 1 and level 2 tables
619  * have base and size attributes to keep their size down.
620  */
621 
622 struct wsfont_level1_glyphmap {
623 	struct wsfont_level2_glyphmap **level2;
624 	int base;	/* High byte for first level2 entry	*/
625 	int size;	/* Number of level2 entries		*/
626 };
627 
628 struct wsfont_level2_glyphmap {
629 	int base;	/* Low byte for first character		*/
630 	int size;	/* Number of characters			*/
631 	void *chars;	/* Pointer to character number entries  */
632 	int width;	/* Size of each entry in bytes (1,2,4)  */
633 };
634 
635 /*
636  * IBM 437 maps
637  */
638 
639 static u_int8_t
640 ibm437_chars_0[] = {
641 	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
642 	16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
643 	32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
644 	48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
645 	64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
646 	80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
647 	96, 97, 98, 99, 100,101,102,103,104,105,106,107,108,109,110,111,
648 	112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
649 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
650 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
651 	255,173,155,156, 0, 157, 0,  0,  0,  0, 166,174,170, 0,  0,  0,
652 	 0, 241,253, 0,  0,  0,  0, 249, 0,  0, 167,175,172,171, 0, 168,
653 	 0,  0,  0,  0, 142,143,146,128, 0, 144, 0,  0,  0,  0,  0,  0,
654 	 0, 165, 0,  0,  0,  0, 153, 0,  0,  0,  0,  0, 154, 0,  0,  0,
655 	133,160,131, 0, 132,134,145,135,138,130,136,137,141,161,140,139,
656 	 0, 164,149,162,147, 0, 148,246, 0, 151,163,150,129, 0,  0, 152
657 },
658 ibm437_chars_1[] = {
659 	159
660 },
661 ibm437_chars_3[] = {
662 	226, 0,  0,  0,  0, 233, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
663 	228, 0,  0, 232, 0,  0, 234, 0,  0,  0,  0,  0,  0,  0, 224,225,
664 	 0, 235,238, 0,  0,  0,  0,  0,  0, 230, 0,  0,  0, 227, 0,  0,
665 	229,231
666 },
667 ibm437_chars_32[] = {
668 	252, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
669 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
670 	 0,  0,  0,  0,  0,  0,  0,  0, 158
671 },
672 ibm437_chars_34[] = {
673 	237, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
674 	 0,  0,  0, 248,250,251, 0,  0,  0, 236, 0,  0,  0,  0,  0,  0,
675 	 0,  0,  0,  0, 239, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
676 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
677 	 0,  0,  0, 247, 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,240,  0,  0,243,
679 	242
680 },
681 ibm437_chars_35[] = {
682 	169, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
683 	244,245
684 },
685 ibm437_chars_37[] = {
686 	196,205,179,186, 0,  0,  0,  0,  0,  0,  0,  0, 218,213,214,201,
687 	191,184,183,187,192,212,211,200,217,190,189,188,195,198, 0,  0,
688 	199, 0,  0, 204,180,181, 0,  0, 182, 0,  0, 185,194, 0,  0, 209,
689 	210, 0,  0, 203,193, 0,  0, 207,208, 0,  0, 202,197, 0,  0, 216,
690 	 0,  0, 215, 0,  0,  0,  0,  0,  0,  0,  0, 206, 0,  0,  0,  0,
691 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  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 	223, 0,  0,  0, 220, 0,  0,  0, 219, 0,  0,  0, 221, 0,  0,  0,
695 	222,176,177,178, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
696 	254
697 };
698 
699 static struct wsfont_level2_glyphmap
700 ibm437_level2_0 = { 0, 256, ibm437_chars_0, 1 },
701 ibm437_level2_1 = { 146, 1, ibm437_chars_1, 1 },
702 ibm437_level2_3 = { 147, 50, ibm437_chars_3, 1 },
703 ibm437_level2_32 = { 127, 41, ibm437_chars_32, 1 },
704 ibm437_level2_34 = { 5, 97, ibm437_chars_34, 1 },
705 ibm437_level2_35 = { 16, 18, ibm437_chars_35, 1 },
706 ibm437_level2_37 = { 0, 161, ibm437_chars_37, 1 };
707 
708 static struct wsfont_level2_glyphmap *ibm437_level1[] = {
709 	&ibm437_level2_0, &ibm437_level2_1, NULL, &ibm437_level2_3,
710 	NULL, NULL, NULL, NULL,
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 	&ibm437_level2_32, NULL, &ibm437_level2_34, &ibm437_level2_35,
718 	NULL, &ibm437_level2_37
719 };
720 
721 static struct wsfont_level1_glyphmap encodings[] = {
722 	/* WSDISPLAY_FONTENC_ISO */
723 	{ NULL, 0, 0 },
724 	/* WSDISPLAY_FONTENC_IBM */
725 	{ ibm437_level1, 0, nitems(ibm437_level1) }
726 };
727 
728 #endif	/* !SMALL_KERNEL */
729 
730 /*
731  * Remap Unicode character to glyph
732  */
733 int
734 wsfont_map_unichar(struct wsdisplay_font *font, int c)
735 {
736 	if (font->encoding == WSDISPLAY_FONTENC_ISO)
737 		return (c);
738 
739 #if !defined(SMALL_KERNEL)
740 	if (font->encoding >= 0 && font->encoding < nitems(encodings)) {
741 		int hi = (c >> 8), lo = c & 255;
742 		struct wsfont_level1_glyphmap *map1 =
743 		    &encodings[font->encoding];
744 		struct wsfont_level2_glyphmap *map2;
745 
746 		hi -= map1->base;
747 
748 		if (hi >= 0 && hi < map1->size &&
749 		    (map2 = map1->level2[hi]) != NULL) {
750 			lo -= map2->base;
751 
752 			if (lo >= 0 && lo < map2->size) {
753 				switch (map2->width) {
754 				case 1:
755 					c = (((u_int8_t *)map2->chars)[lo]);
756 					break;
757 				case 2:
758 					c = (((u_int16_t *)map2->chars)[lo]);
759 					break;
760 				case 4:
761 					c = (((u_int32_t *)map2->chars)[lo]);
762 					break;
763 				}
764 
765 				if (c != 0 || lo == 0)
766 					return (c);
767 			}
768 		}
769 	}
770 #endif	/* !SMALL_KERNEL */
771 
772 	return (-1);
773 }
774