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