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