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