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