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