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