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