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