xref: /netbsd-src/sys/dev/wsfont/wsfont.c (revision 23c8222edbfb0f0932d88a8351d3a0cf817dfb9e)
1 /* 	$NetBSD: wsfont.c,v 1.36 2004/04/23 21:29:16 itojun Exp $	*/
2 
3 /*-
4  * Copyright (c) 1999, 2000, 2001, 2002 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Andrew Doran.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by the NetBSD
21  *	Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: wsfont.c,v 1.36 2004/04/23 21:29:16 itojun Exp $");
41 
42 #include "opt_wsfont.h"
43 
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/time.h>
47 #include <sys/malloc.h>
48 #include <sys/queue.h>
49 
50 #include <dev/wscons/wsdisplayvar.h>
51 #include <dev/wscons/wsconsio.h>
52 #include <dev/wsfont/wsfont.h>
53 
54 #undef HAVE_FONT
55 
56 #ifdef FONT_QVSS8x15
57 #define HAVE_FONT 1
58 #include <dev/wsfont/qvss8x15.h>
59 #endif
60 
61 #ifdef FONT_GALLANT12x22
62 #define HAVE_FONT 1
63 #include <dev/wsfont/gallant12x22.h>
64 #endif
65 
66 #ifdef FONT_LUCIDA16x29
67 #define HAVE_FONT 1
68 #include <dev/wsfont/lucida16x29.h>
69 #endif
70 
71 #ifdef FONT_VT220L8x8
72 #define HAVE_FONT 1
73 #include <dev/wsfont/vt220l8x8.h>
74 #endif
75 
76 #ifdef FONT_VT220L8x10
77 #define HAVE_FONT 1
78 #include <dev/wsfont/vt220l8x10.h>
79 #endif
80 
81 #ifdef FONT_VT220L8x16
82 #define HAVE_FONT 1
83 #include <dev/wsfont/vt220l8x16.h>
84 #endif
85 
86 #ifdef FONT_VT220ISO8x16
87 #define HAVE_FONT 1
88 #include <dev/wsfont/vt220iso8x16.h>
89 #endif
90 
91 #ifdef FONT_VT220KOI8x10_KOI8_R
92 #define HAVE_FONT 1
93 #include <dev/wsfont/vt220koi8x10.h>
94 #endif
95 
96 #ifdef FONT_VT220KOI8x10_KOI8_U
97 #define HAVE_FONT 1
98 #define KOI8_U
99 #include <dev/wsfont/vt220koi8x10.h>
100 #undef KOI8_U
101 #endif
102 
103 #ifdef FONT_SONY8x16
104 #define HAVE_FONT 1
105 #include <dev/wsfont/sony8x16.h>
106 #endif
107 
108 #ifdef FONT_SONY12x24
109 #define HAVE_FONT 1
110 #include <dev/wsfont/sony12x24.h>
111 #endif
112 
113 #ifdef FONT_OMRON12x20
114 #define HAVE_FONT 1
115 #include <dev/wsfont/omron12x20.h>
116 #endif
117 
118 /* Make sure we always have at least one font. */
119 #ifndef HAVE_FONT
120 #define HAVE_FONT 1
121 #define FONT_BOLD8x16 1
122 #endif
123 
124 #ifdef FONT_BOLD8x16
125 #include <dev/wsfont/bold8x16.h>
126 #endif
127 
128 #define	WSFONT_IDENT_MASK	0xffffff00
129 #define	WSFONT_IDENT_SHIFT	8
130 #define	WSFONT_BITO_MASK	0x000000f0
131 #define	WSFONT_BITO_SHIFT	4
132 #define	WSFONT_BYTEO_MASK	0x0000000f
133 #define	WSFONT_BYTEO_SHIFT	0
134 
135 #define WSFONT_BUILTIN	0x01	/* In wsfont.c */
136 #define WSFONT_STATIC	0x02	/* Font structures not malloc()ed */
137 #define WSFONT_COPY	0x04	/* Copy of existing font in table */
138 
139 /* Placeholder struct used for linked list */
140 struct font {
141 	TAILQ_ENTRY(font) chain;
142 	struct	wsdisplay_font *font;
143 	u_int	lockcount;
144 	u_int	cookie;
145 	u_int	flags;
146 };
147 
148 /* Our list of built-in fonts */
149 static struct font builtin_fonts[] = {
150 #ifdef FONT_BOLD8x16
151 	{ { NULL }, &bold8x16, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN  },
152 #endif
153 #ifdef FONT_ISO8x16
154 	{ { NULL }, &iso8x16, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
155 #endif
156 #ifdef FONT_COURIER11x18
157 	{ { NULL }, &courier11x18, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
158 #endif
159 #ifdef FONT_GALLANT12x22
160 	{ { NULL }, &gallant12x22, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
161 #endif
162 #ifdef FONT_LUCIDA16x29
163 	{ { NULL }, &lucida16x29, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
164 #endif
165 #ifdef FONT_QVSS8x15
166 	{ { NULL }, &qvss8x15, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
167 #endif
168 #ifdef FONT_VT220L8x8
169 	{ { NULL }, &vt220l8x8, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
170 #endif
171 #ifdef FONT_VT220L8x10
172 	{ { NULL }, &vt220l8x10, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
173 #endif
174 #ifdef FONT_VT220L8x16
175 	{ { NULL }, &vt220l8x16, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
176 #endif
177 #ifdef FONT_VT220ISO8x16
178 	{ { NULL }, &vt220iso8x16, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
179 #endif
180 #ifdef FONT_VT220KOI8x10_KOI8_R
181 	{ { NULL }, &vt220kr8x10, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
182 #endif
183 #ifdef FONT_VT220KOI8x10_KOI8_U
184 	{ { NULL }, &vt220ku8x10, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
185 #endif
186 #ifdef FONT_SONY8x16
187 	{ { NULL }, &sony8x16, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
188 #endif
189 #ifdef FONT_SONY12x24
190 	{ { NULL }, &sony12x24, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
191 #endif
192 #ifdef FONT_OMRON12x20
193 	{ { NULL }, &omron12x20, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
194 #endif
195 	{ { NULL }, NULL, 0, 0, 0 },
196 };
197 
198 static TAILQ_HEAD(,font)	list;
199 static int	ident;
200 
201 /* Reverse the bit order in a byte */
202 static const u_char reverse[256] = {
203 	0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
204 	0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
205 	0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
206 	0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
207 	0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
208 	0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
209 	0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
210 	0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
211 	0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
212 	0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
213 	0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
214 	0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
215 	0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
216 	0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
217 	0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
218 	0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
219 	0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
220 	0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
221 	0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
222 	0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
223 	0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
224 	0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
225 	0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
226 	0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
227 	0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
228 	0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
229 	0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
230 	0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
231 	0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
232 	0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
233 	0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
234 	0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
235 };
236 
237 static struct	font *wsfont_find0(int, int);
238 static struct	font *wsfont_add0(struct wsdisplay_font *, int);
239 static void	wsfont_revbit(struct wsdisplay_font *);
240 static void	wsfont_revbyte(struct wsdisplay_font *);
241 static int __inline__ wsfont_make_cookie(int, int, int);
242 
243 static int __inline__
244 wsfont_make_cookie(int ident, int bito, int byteo)
245 {
246 
247 	return ((ident & WSFONT_IDENT_MASK) |
248 	    (bito << WSFONT_BITO_SHIFT) |
249 	    (byteo << WSFONT_BYTEO_SHIFT));
250 }
251 
252 static void
253 wsfont_revbit(struct wsdisplay_font *font)
254 {
255 	u_char *p, *m;
256 
257 	p = (u_char *)font->data;
258 	m = p + font->stride * font->numchars * font->fontheight;
259 
260 	for (; p < m; p++)
261 		*p = reverse[*p];
262 }
263 
264 static void
265 wsfont_revbyte(struct wsdisplay_font *font)
266 {
267 	int x, l, r, nr;
268 	u_char *rp;
269 
270 	if (font->stride == 1)
271 		return;
272 
273 	rp = (u_char *)font->data;
274 	nr = font->numchars * font->fontheight;
275 
276 	while (nr--) {
277 		l = 0;
278 		r = font->stride - 1;
279 
280 		while (l < r) {
281 			x = rp[l];
282 			rp[l] = rp[r];
283 			rp[r] = x;
284 			l++, r--;
285 		}
286 
287 		rp += font->stride;
288 	}
289 }
290 
291 void
292 wsfont_enum(void (*cb)(const char *, int, int, int))
293 {
294 	struct wsdisplay_font *f;
295 	struct font *ent;
296 
297 	TAILQ_FOREACH(ent, &list, chain) {
298 		f = ent->font;
299 		cb(f->name, f->fontwidth, f->fontheight, f->stride);
300 	}
301 }
302 
303 void
304 wsfont_init(void)
305 {
306 	struct font *ent;
307 	static int again;
308 	int i;
309 
310 	if (again != 0)
311 		return;
312 	again = 1;
313 
314 	TAILQ_INIT(&list);
315 	ent = builtin_fonts;
316 
317 	for (i = 0; builtin_fonts[i].font != NULL; i++, ent++) {
318 		ident += (1 << WSFONT_IDENT_SHIFT);
319 		ent->cookie = wsfont_make_cookie(ident,
320 		    ent->font->bitorder, ent->font->byteorder);
321 		TAILQ_INSERT_TAIL(&list, ent, chain);
322 	}
323 }
324 
325 static struct font *
326 wsfont_find0(int cookie, int mask)
327 {
328 	struct font *ent;
329 
330 	TAILQ_FOREACH(ent, &list, chain) {
331 		if ((ent->cookie & mask) == (cookie & mask))
332 			return (ent);
333 	}
334 
335 	return (NULL);
336 }
337 
338 int
339 wsfont_matches(struct wsdisplay_font *font, const char *name,
340 	       int width, int height, int stride)
341 {
342 
343 	if (height != 0 && font->fontheight != height)
344 		return (0);
345 
346 	if (width != 0 && font->fontwidth != width)
347 		return (0);
348 
349 	if (stride != 0 && font->stride != stride)
350 		return (0);
351 
352 	if (name != NULL && strcmp(font->name, name) != 0)
353 		return (0);
354 
355 	return (1);
356 }
357 
358 int
359 wsfont_find(const char *name, int width, int height, int stride, int bito, int byteo)
360 {
361 	struct font *ent;
362 
363 	TAILQ_FOREACH(ent, &list, chain) {
364 		if (wsfont_matches(ent->font, name, width, height, stride))
365 			return (wsfont_make_cookie(ent->cookie, bito, byteo));
366 	}
367 
368 	return (-1);
369 }
370 
371 static struct font *
372 wsfont_add0(struct wsdisplay_font *font, int copy)
373 {
374 	struct font *ent;
375 	size_t size;
376 
377 	ent = malloc(sizeof(struct font), M_DEVBUF, M_WAITOK | M_ZERO);
378 
379 	/* Is this font statically allocated? */
380 	if (!copy) {
381 		ent->font = font;
382 		ent->flags = WSFONT_STATIC;
383 	} else {
384 		void *data;
385 		char *name;
386 
387 		ent->font = malloc(sizeof(struct wsdisplay_font), M_DEVBUF,
388 		    M_WAITOK);
389 		memcpy(ent->font, font, sizeof(*ent->font));
390 
391 		size = font->fontheight * font->numchars * font->stride;
392 		data = malloc(size, M_DEVBUF, M_WAITOK);
393 		memcpy(data, font->data, size);
394 		ent->font->data = data;
395 
396 		name = malloc(strlen(font->name) + 1, M_DEVBUF, M_WAITOK);
397 		strlcpy(name, font->name, strlen(font->name) + 1);
398 		ent->font->name = name;
399 	}
400 
401 	TAILQ_INSERT_TAIL(&list, ent, chain);
402 	return (ent);
403 }
404 
405 int
406 wsfont_add(struct wsdisplay_font *font, int copy)
407 {
408 	struct font *ent;
409 
410 	/* Don't allow exact duplicates */
411 	if (wsfont_find(font->name, font->fontwidth, font->fontheight,
412 	    font->stride, 0, 0) >= 0)
413 		return (EEXIST);
414 
415 	ent = wsfont_add0(font, copy);
416 
417 	ident += (1 << WSFONT_IDENT_SHIFT);
418 	ent->cookie = wsfont_make_cookie(ident, font->bitorder,
419 	    font->byteorder);
420 
421 	return (0);
422 }
423 
424 int
425 wsfont_remove(int cookie)
426 {
427 	struct font *ent;
428 
429 	if ((ent = wsfont_find0(cookie, 0xffffffff)) == NULL)
430 		return (ENOENT);
431 
432 	if ((ent->flags & WSFONT_BUILTIN) != 0 || ent->lockcount != 0)
433 		return (EBUSY);
434 
435 	if ((ent->flags & WSFONT_STATIC) == 0) {
436 		free((void *)ent->font->data, M_DEVBUF);
437 		free((void *)ent->font->name, M_DEVBUF);
438 		free(ent->font, M_DEVBUF);
439 	}
440 
441 	TAILQ_REMOVE(&list, ent, chain);
442 	free(ent, M_DEVBUF);
443 
444 	return (0);
445 }
446 
447 int
448 wsfont_lock(int cookie, struct wsdisplay_font **ptr)
449 {
450 	struct font *ent, *neu;
451 	int bito, byteo;
452 
453 	if ((ent = wsfont_find0(cookie, 0xffffffff)) == NULL) {
454 		if ((ent = wsfont_find0(cookie, WSFONT_IDENT_MASK)) == NULL)
455 			return (ENOENT);
456 
457 		bito = (cookie & WSFONT_BITO_MASK) >> WSFONT_BITO_SHIFT;
458 		byteo = (cookie & WSFONT_BYTEO_MASK) >> WSFONT_BYTEO_SHIFT;
459 
460 		if (ent->lockcount != 0) {
461 			neu = wsfont_add0(ent->font, 1);
462 			neu->flags |= WSFONT_COPY;
463 
464 			aprint_debug("wsfont: font '%s' bito %d byteo %d "
465 			    "copied to bito %d byteo %d\n",
466 			    ent->font->name,
467 			    ent->font->bitorder, ent->font->byteorder,
468 			    bito, byteo);
469 
470 			ent = neu;
471 		}
472 
473 		if (bito && bito != ent->font->bitorder) {
474 			wsfont_revbit(ent->font);
475 			ent->font->bitorder = bito;
476 		}
477 
478 		if (byteo && byteo != ent->font->byteorder) {
479 			wsfont_revbyte(ent->font);
480 			ent->font->byteorder = byteo;
481 		}
482 
483 		ent->cookie = cookie;
484 	}
485 
486 	ent->lockcount++;
487 	*ptr = ent->font;
488 	return (0);
489 }
490 
491 int
492 wsfont_unlock(int cookie)
493 {
494 	struct font *ent;
495 
496 	if ((ent = wsfont_find0(cookie, 0xffffffff)) == NULL)
497 		return (ENOENT);
498 
499 	if (ent->lockcount == 0)
500 		panic("wsfont_unlock: font not locked");
501 
502 	if (--ent->lockcount == 0 && (ent->flags & WSFONT_COPY) != 0)
503 		wsfont_remove(cookie);
504 
505 	return (0);
506 }
507 
508 /*
509  * Unicode to font encoding mappings
510  */
511 
512 /*
513  * To save memory, font encoding tables use a two level lookup.  First the
514  * high byte of the Unicode is used to lookup the level 2 table, then the
515  * low byte indexes that table.  Level 2 tables that are not needed are
516  * omitted (NULL), and both level 1 and level 2 tables have base and size
517  * attributes to keep their size down.
518  */
519 
520 struct wsfont_level1_glyphmap {
521 	const struct	wsfont_level2_glyphmap **level2;
522 	int	base;	/* High byte for first level2 entry	*/
523 	int	size;	/* Number of level2 entries		*/
524 };
525 
526 struct wsfont_level2_glyphmap {
527 	int	base;	/* Low byte for first character		*/
528 	int	size;	/* Number of characters			*/
529 	const void	*chars;	/* Pointer to character number entries  */
530 	int	width;	/* Size of each entry in bytes (1,2,4)  */
531 };
532 
533 #define null16			\
534 	NULL, NULL, NULL, NULL,	\
535 	NULL, NULL, NULL, NULL,	\
536 	NULL, NULL, NULL, NULL,	\
537 	NULL, NULL, NULL, NULL
538 
539 /*
540  * IBM 437 maps
541  */
542 
543 static const u_int8_t ibm437_chars_0[] = {
544 	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
545 	16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
546 	32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
547 	48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
548 	64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
549 	80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
550 	96, 97, 98, 99, 100,101,102,103,104,105,106,107,108,109,110,111,
551 	112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
552 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
553 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
554 	255,173,155,156, 0, 157, 0,  0,  0,  0, 166,174,170, 0,  0,  0,
555 	 0, 241,253, 0,  0,  0,  0, 249, 0,  0, 167,175,172,171, 0, 168,
556 	 0,  0,  0,  0, 142,143,146,128, 0, 144, 0,  0,  0,  0,  0,  0,
557 	 0, 165, 0,  0,  0,  0, 153, 0,  0,  0,  0,  0, 154, 0,  0,  0,
558 	133,160,131, 0, 132,134,145,135,138,130,136,137,141,161,140,139,
559 	 0, 164,149,162,147, 0, 148,246, 0, 151,163,150,129, 0,  0, 152
560 };
561 
562 static const u_int8_t ibm437_chars_1[] = {
563 	159
564 };
565 
566 static const u_int8_t ibm437_chars_3[] = {
567 	226, 0,  0,  0,  0, 233, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
568 	228, 0,  0, 232, 0,  0, 234, 0,  0,  0,  0,  0,  0,  0, 224,225,
569 	 0, 235,238, 0,  0,  0,  0,  0,  0, 230, 0,  0,  0, 227, 0,  0,
570 	229,231
571 };
572 
573 static const u_int8_t ibm437_chars_32[] = {
574 	252, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
575 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
576 	 0,  0,  0,  0,  0,  0,  0,  0, 158
577 };
578 
579 static const u_int8_t ibm437_chars_34[] = {
580 	237, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
581 	 0,  0,  0, 248,250,251, 0,  0,  0, 236, 0,  0,  0,  0,  0,  0,
582 	 0,  0,  0,  0, 239, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
583 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
584 	 0,  0,  0, 247, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
585 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,240,  0,  0,243,
586 	242
587 };
588 
589 static const u_int8_t ibm437_chars_35[] = {
590 	169, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
591 	244,245
592 };
593 
594 static const u_int8_t ibm437_chars_37[] = {
595 	196,205,179,186, 0,  0,  0,  0,  0,  0,  0,  0, 218,213,214,201,
596 	191,184,183,187,192,212,211,200,217,190,189,188,195,198, 0,  0,
597 	199, 0,  0, 204,180,181, 0,  0, 182, 0,  0, 185,194, 0,  0, 209,
598 	210, 0,  0, 203,193, 0,  0, 207,208, 0,  0, 202,197, 0,  0, 216,
599 	 0,  0, 215, 0,  0,  0,  0,  0,  0,  0,  0, 206, 0,  0,  0,  0,
600 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
601 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
602 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
603 	223, 0,  0,  0, 220, 0,  0,  0, 219, 0,  0,  0, 221, 0,  0,  0,
604 	222,176,177,178, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
605 	254
606 };
607 
608 static const struct wsfont_level2_glyphmap ibm437_level2_0 =
609     { 0, 256, ibm437_chars_0, 1 };
610 
611 static const struct wsfont_level2_glyphmap ibm437_level2_1 =
612     { 146, 1, ibm437_chars_1, 1 };
613 
614 static const struct wsfont_level2_glyphmap ibm437_level2_3 =
615     { 147, 50, ibm437_chars_3, 1 };
616 
617 static const struct wsfont_level2_glyphmap ibm437_level2_32 =
618     { 127, 41, ibm437_chars_32, 1 };
619 
620 static const struct wsfont_level2_glyphmap ibm437_level2_34 =
621     { 5, 97, ibm437_chars_34, 1 };
622 
623 static const struct wsfont_level2_glyphmap ibm437_level2_35 =
624     { 16, 18, ibm437_chars_35, 1 };
625 
626 static const struct wsfont_level2_glyphmap ibm437_level2_37 =
627     { 0, 161, ibm437_chars_37, 1 };
628 
629 static const struct wsfont_level2_glyphmap *ibm437_level1[] = {
630 	&ibm437_level2_0, &ibm437_level2_1, NULL, &ibm437_level2_3,
631 	NULL, NULL, NULL, NULL,
632 	NULL, NULL, NULL, NULL,
633 	NULL, NULL, NULL, NULL,
634 	NULL, NULL, NULL, NULL,
635 	NULL, NULL, NULL, NULL,
636 	NULL, NULL, NULL, NULL,
637 	NULL, NULL, NULL, NULL,
638 	&ibm437_level2_32, NULL, &ibm437_level2_34, &ibm437_level2_35,
639 	NULL, &ibm437_level2_37
640 };
641 
642 /*
643  * ISO-8859-7 maps
644  */
645 static const u_int8_t iso7_chars_0[] = {
646 	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
647 	16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
648 	32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
649 	48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
650 	64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
651 	80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
652 	96, 97, 98, 99, 100,101,102,103,104,105,106,107,108,109,110,111,
653 	112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
654 	128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
655 	144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
656 	160, 0,  0, 163, 0,  0, 166,167,168,169, 0, 171,172,173, 0,  0,
657 	176,177,178,179,180, 0,  0, 183, 0,  0,  0, 187, 0, 189
658 };
659 
660 static const u_int8_t iso7_chars_3[] = {
661 	182, 0, 184,185,186, 0, 188, 0, 190,191,192,193,194,195,196,197,
662 	198,199,200,201,202,203,204,205,206,207,208,209, 0, 211,212,213,
663 	214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,
664 	230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,
665 	246,247,248,249,250,251,252,253,254, 0,  0,  0,  0,  0,  0,  0,
666 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
667 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 181
668 };
669 
670 static const u_int8_t iso7_chars_32[] = {
671 	175, 0,  0,  0,  0, 162, 0, 161
672 };
673 
674 static const struct wsfont_level2_glyphmap iso7_level2_0 =
675     { 0, 190, iso7_chars_0, 1 };
676 
677 static const struct wsfont_level2_glyphmap iso7_level2_3 =
678     { 134, 111, iso7_chars_3, 1 };
679 
680 static const struct wsfont_level2_glyphmap iso7_level2_32 =
681     { 20, 8, iso7_chars_32, 1 };
682 
683 static const struct wsfont_level2_glyphmap *iso7_level1[] = {
684 	&iso7_level2_0, NULL, NULL, &iso7_level2_3,
685 	NULL, NULL, NULL, NULL,
686 	NULL, NULL, NULL, NULL,
687 	NULL, NULL, NULL, NULL,
688 	NULL, NULL, NULL, NULL,
689 	NULL, NULL, NULL, NULL,
690 	NULL, NULL, NULL, NULL,
691 	NULL, NULL, NULL, NULL,
692 	&iso7_level2_32
693 };
694 
695 static const struct wsfont_level1_glyphmap encodings[] = {
696 	{ NULL, 0, 0 },			/* WSDISPLAY_FONTENC_ISO */
697 	{ ibm437_level1, 0, 38 },	/* WSDISPLAY_FONTENC_IBM */
698 	{ NULL, 0, 0 },			/* WSDISPLAY_FONTENC_PCVT */
699 	{ iso7_level1, 0, 33 },		/* WSDISPLAY_FONTENC_ISO7 */
700 };
701 
702 #define MAX_ENCODING (sizeof(encodings) / sizeof(encodings[0]))
703 
704 /*
705  * Remap Unicode character to glyph
706  */
707 int
708 wsfont_map_unichar(struct wsdisplay_font *font, int c)
709 {
710 	const struct wsfont_level1_glyphmap *map1;
711 	const struct wsfont_level2_glyphmap *map2;
712 	int hi, lo;
713 
714 	if (font->encoding == WSDISPLAY_FONTENC_ISO)
715 		return (c);
716 
717 	if (font->encoding < 0 || font->encoding > MAX_ENCODING)
718 		return (-1);
719 
720 	hi = (c >> 8);
721 	lo = c & 255;
722 	map1 = &encodings[font->encoding];
723 
724 	if (hi < map1->base || hi >= map1->base + map1->size)
725 		return (-1);
726 
727 	map2 = map1->level2[hi - map1->base];
728 
729 	if (map2 == NULL || lo < map2->base || lo >= map2->base + map2->size)
730 		return (-1);
731 
732 	lo -= map2->base;
733 
734 	switch(map2->width) {
735 	case 1:
736 		c = (((const u_int8_t *)map2->chars)[lo]);
737 		break;
738 	case 2:
739 		c = (((const u_int16_t *)map2->chars)[lo]);
740 		break;
741 	case 4:
742 		c = (((const u_int32_t *)map2->chars)[lo]);
743 		break;
744 	}
745 
746 	if (c == 0 && lo != 0)
747 		return (-1);
748 
749 	return (c);
750 }
751