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