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