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