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