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