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