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