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