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