wsfont.c revision 1.60
1/*	$OpenBSD: wsfont.c,v 1.60 2021/11/01 18:43: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(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#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
132struct font {
133	TAILQ_ENTRY(font) chain;
134	struct	wsdisplay_font *font;
135	u_short	lockcount;
136	u_short	cookie;
137	u_short	flg;
138};
139TAILQ_HEAD(, font) fontlist;
140
141/* Our list of built-in fonts */
142static 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 */
183static 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
220static 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 */
227static void	wsfont_revbit(struct wsdisplay_font *);
228static void
229wsfont_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 */
247static void	wsfont_revbyte(struct wsdisplay_font *);
248static void
249wsfont_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 */
280void
281wsfont_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
297void wsfont_rotate_cw(struct wsdisplay_font *, char *, int);
298void wsfont_rotate_ccw(struct wsdisplay_font *, char *, int);
299struct wsdisplay_font *wsfont_rotate_internal(struct wsdisplay_font *, int);
300
301void
302wsfont_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
328void
329wsfont_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
356struct wsdisplay_font *
357wsfont_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
400int
401wsfont_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 */
426void
427wsfont_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 */
446static struct font *
447wsfont_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 */
461int
462wsfont_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 */
493int
494wsfont_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 */
548int
549wsfont_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 */
598int
599wsfont_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
631struct 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
637struct 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
648static u_int8_t
649ibm437_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},
667ibm437_chars_1[] = {
668	159
669},
670ibm437_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},
676ibm437_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},
681ibm437_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},
690ibm437_chars_35[] = {
691	169, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
692	244,245
693},
694ibm437_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
708static struct wsfont_level2_glyphmap
709ibm437_level2_0 = { 0, 256, ibm437_chars_0, 1 },
710ibm437_level2_1 = { 146, 1, ibm437_chars_1, 1 },
711ibm437_level2_3 = { 147, 50, ibm437_chars_3, 1 },
712ibm437_level2_32 = { 127, 41, ibm437_chars_32, 1 },
713ibm437_level2_34 = { 5, 97, ibm437_chars_34, 1 },
714ibm437_level2_35 = { 16, 18, ibm437_chars_35, 1 },
715ibm437_level2_37 = { 0, 161, ibm437_chars_37, 1 };
716
717static 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
730static 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 */
742int
743wsfont_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