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