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