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