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