Home | History | Annotate | Line # | Download | only in wsfont
wsfont.c revision 1.71
      1 /* 	$NetBSD: wsfont.c,v 1.71 2020/11/23 12:15:39 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.71 2020/11/23 12:15:39 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_MONO12x22
    134 #define HAVE_FONT 1
    135 #include <dev/wsfont/Droid_Sans_Mono_12x22.h>
    136 #endif
    137 
    138 #ifdef FONT_DROID_SANS_MONO9x18
    139 #define HAVE_FONT 1
    140 #include <dev/wsfont/Droid_Sans_Mono_9x18.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 struct wsdisplay_font *wsfont_rotate_cw_internal(struct wsdisplay_font *);
    422 struct wsdisplay_font *wsfont_rotate_ccw_internal(struct wsdisplay_font *);
    423 
    424 struct wsdisplay_font *
    425 wsfont_rotate_cw_internal(struct wsdisplay_font *font)
    426 {
    427 	int b, n, r, namelen, newstride;
    428 	struct wsdisplay_font *newfont;
    429 	char *newname, *newbits;
    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", namelen);
    440 	newfont->name = newname;
    441 
    442 	/* Allocate a buffer big enough for the rotated font. */
    443 	newstride = (font->fontheight + 7) / 8;
    444 	newbits = malloc(newstride * font->fontwidth * font->numchars,
    445 	    M_DEVBUF, M_WAITOK|M_ZERO);
    446 
    447 	/* Rotate the font a bit at a time. */
    448 	for (n = 0; n < font->numchars; n++) {
    449 		unsigned char *ch = (unsigned char *)font->data +
    450 		    (n * font->stride * font->fontheight);
    451 
    452 		for (r = 0; r < font->fontheight; r++) {
    453 			for (b = 0; b < font->fontwidth; b++) {
    454 				unsigned char *rb;
    455 
    456 				rb = ch + (font->stride * r) + (b / 8);
    457 				if (*rb & (0x80 >> (b % 8))) {
    458 					unsigned char *rrb;
    459 
    460 					rrb = newbits + newstride - 1 - (r / 8)
    461 					    + (n * newstride * font->fontwidth)
    462 					    + (newstride * b);
    463 					*rrb |= (1 << (r % 8));
    464 				}
    465 			}
    466 		}
    467 	}
    468 
    469 	newfont->data = newbits;
    470 
    471 	/* Update font sizes. */
    472 	newfont->stride = newstride;
    473 	newfont->fontwidth = font->fontheight;
    474 	newfont->fontheight = font->fontwidth;
    475 
    476 	if (wsfont_add(newfont, 0) != 0) {
    477 		/*
    478 		 * If we seem to have rotated this font already, drop the
    479 		 * new one...
    480 		 */
    481 		free(newbits, M_DEVBUF);
    482 		free(newfont, M_DEVBUF);
    483 		newfont = NULL;
    484 	}
    485 
    486 	return (newfont);
    487 }
    488 
    489 struct wsdisplay_font *
    490 wsfont_rotate_ccw_internal(struct wsdisplay_font *font)
    491 {
    492 	int b, n, r, namelen, newstride;
    493 	struct wsdisplay_font *newfont;
    494 	char *newname, *newbits;
    495 
    496 	/* Duplicate the existing font... */
    497 	newfont = malloc(sizeof(*font), M_DEVBUF, M_WAITOK);
    498 
    499 	*newfont = *font;
    500 
    501 	namelen = strlen(font->name) + 4;
    502 	newname = malloc(namelen, M_DEVBUF, M_WAITOK);
    503 	strlcpy(newname, font->name, namelen);
    504 	strlcat(newname, "ccw", namelen);
    505 	newfont->name = newname;
    506 
    507 	/* Allocate a buffer big enough for the rotated font. */
    508 	newstride = (font->fontheight + 7) / 8;
    509 	newbits = malloc(newstride * font->fontwidth * font->numchars,
    510 	    M_DEVBUF, M_WAITOK|M_ZERO);
    511 
    512 	/* Rotate the font a bit at a time. */
    513 	for (n = 0; n < font->numchars; n++) {
    514 		unsigned char *ch = (unsigned char *)font->data +
    515 		    (n * font->stride * font->fontheight);
    516 
    517 		for (r = 0; r < font->fontheight; r++) {
    518 			for (b = 0; b < font->fontwidth; b++) {
    519 				unsigned char *rb;
    520 
    521 				rb = ch + (font->stride * r) + (b / 8);
    522 				if (*rb & (0x80 >> (b % 8))) {
    523 					unsigned char *rrb;
    524 					int w = font->fontwidth;
    525 
    526 					rrb = newbits + (r / 8)
    527 					    + (n * newstride * w)
    528 					    + (newstride * (w - 1 - b));
    529 					*rrb |= (0x80 >> (r % 8));
    530 				}
    531 			}
    532 		}
    533 	}
    534 
    535 	newfont->data = newbits;
    536 
    537 	/* Update font sizes. */
    538 	newfont->stride = newstride;
    539 	newfont->fontwidth = font->fontheight;
    540 	newfont->fontheight = font->fontwidth;
    541 
    542 	if (wsfont_add(newfont, 0) != 0) {
    543 		/*
    544 		 * If we seem to have rotated this font already, drop the
    545 		 * new one...
    546 		 */
    547 		free(newbits, M_DEVBUF);
    548 		free(newfont, M_DEVBUF);
    549 		newfont = NULL;
    550 	}
    551 
    552 	return (newfont);
    553 }
    554 
    555 int
    556 wsfont_rotate(int cookie, int rotate)
    557 {
    558 	int s, ncookie;
    559 	struct wsdisplay_font *font;
    560 	struct font *origfont;
    561 
    562 	s = splhigh();
    563 	origfont = wsfont_find0(cookie, 0xffffffff);
    564 	splx(s);
    565 
    566 	switch (rotate) {
    567 	case WSFONT_ROTATE_CW:
    568 		font = wsfont_rotate_cw_internal(origfont->font);
    569 		if (font == NULL)
    570 			return (-1);
    571 		break;
    572 
    573 	case WSFONT_ROTATE_CCW:
    574 		font = wsfont_rotate_ccw_internal(origfont->font);
    575 		if (font == NULL)
    576 			return (-1);
    577 		break;
    578 
    579 	case WSFONT_ROTATE_UD:
    580 	default:
    581 		return (-1);
    582 	}
    583 	/* rotation works only with bitmap fonts so far */
    584 	ncookie = wsfont_find(font->name, font->fontwidth, font->fontheight,
    585 	    font->stride, 0, 0, WSFONT_FIND_BITMAP);
    586 
    587 	return (ncookie);
    588 }
    589 
    590 #endif	/* NRASOPS_ROTATION */
    591 
    592 void
    593 wsfont_init(void)
    594 {
    595 	struct font *ent;
    596 	static int again;
    597 	int i;
    598 
    599 	if (again != 0)
    600 		return;
    601 	again = 1;
    602 
    603 	TAILQ_INIT(&list);
    604 	ent = builtin_fonts;
    605 
    606 	for (i = 0; builtin_fonts[i].font != NULL; i++, ent++) {
    607 		ident += (1 << WSFONT_IDENT_SHIFT);
    608 		ent->cookie = wsfont_make_cookie(ident,
    609 		    ent->font->bitorder, ent->font->byteorder);
    610 		TAILQ_INSERT_TAIL(&list, ent, chain);
    611 	}
    612 }
    613 
    614 static struct font *
    615 wsfont_find0(int cookie, int mask)
    616 {
    617 	struct font *ent;
    618 
    619 	TAILQ_FOREACH(ent, &list, chain) {
    620 		if ((ent->cookie & mask) == (cookie & mask))
    621 			return (ent);
    622 	}
    623 
    624 	return (NULL);
    625 }
    626 
    627 int
    628 wsfont_matches(struct wsdisplay_font *font, const char *name,
    629 	       int width, int height, int stride, int flags)
    630 {
    631 	int score = 20000;
    632 
    633 	/* first weed out fonts the caller doesn't claim support for */
    634 	if (FONT_IS_ALPHA(font)) {
    635 		if (flags & WSFONT_PREFER_ALPHA)
    636 			score++;
    637 		if ((flags & WSFONT_FIND_ALPHA) == 0)
    638 			return 0;
    639 	} else {
    640 		if ((flags & WSFONT_FIND_BITMAP) == 0)
    641 			return 0;
    642 	}
    643 
    644 	if (height != 0 && font->fontheight != height)
    645 		return (0);
    646 
    647 	if (width != 0) {
    648 		if ((flags & WSFONT_FIND_BESTWIDTH) == 0) {
    649 			if (font->fontwidth != width)
    650 				return (0);
    651 		} else {
    652 			if (font->fontwidth > width)
    653 				score -= 10000 + uimin(font->fontwidth - width, 9999);
    654 			else
    655 				score -= uimin(width - font->fontwidth, 9999);
    656 		}
    657 	}
    658 
    659 	if (stride != 0 && font->stride != stride)
    660 		return (0);
    661 
    662 	if (name != NULL && strcmp(font->name, name) != 0)
    663 		return (0);
    664 
    665 	return (score);
    666 }
    667 
    668 int
    669 wsfont_find(const char *name, int width, int height, int stride, int bito, int byteo, int flags)
    670 {
    671 	struct font *ent, *bestent = NULL;
    672 	int score, bestscore = 0;
    673 
    674 	TAILQ_FOREACH(ent, &list, chain) {
    675 		score = wsfont_matches(ent->font, name,
    676 				width, height, stride, flags);
    677 		if (score > bestscore) {
    678 			bestscore = score;
    679 			bestent = ent;
    680 		}
    681 	}
    682 
    683 	if (bestent != NULL)
    684 		return (wsfont_make_cookie(bestent->cookie, bito, byteo));
    685 
    686 	return (-1);
    687 }
    688 
    689 void
    690 wsfont_walk(void (*matchfunc)(struct wsdisplay_font *, void *, int), void *cookie)
    691 {
    692 	struct font *ent;
    693 
    694 	TAILQ_FOREACH(ent, &list, chain) {
    695 		matchfunc(ent->font, cookie, ent->cookie);
    696 	}
    697 }
    698 
    699 static struct font *
    700 wsfont_add0(struct wsdisplay_font *font, int copy)
    701 {
    702 	struct font *ent;
    703 	size_t size;
    704 
    705 	ent = malloc(sizeof(struct font), M_DEVBUF, M_WAITOK | M_ZERO);
    706 
    707 	/* Is this font statically allocated? */
    708 	if (!copy) {
    709 		ent->font = font;
    710 		ent->flags = WSFONT_STATIC;
    711 	} else {
    712 		void *data;
    713 		char *name;
    714 
    715 		ent->font = malloc(sizeof(struct wsdisplay_font), M_DEVBUF,
    716 		    M_WAITOK);
    717 		memcpy(ent->font, font, sizeof(*ent->font));
    718 
    719 		size = font->fontheight * font->numchars * font->stride;
    720 		data = malloc(size, M_DEVBUF, M_WAITOK);
    721 		memcpy(data, font->data, size);
    722 		ent->font->data = data;
    723 
    724 		name = malloc(strlen(font->name) + 1, M_DEVBUF, M_WAITOK);
    725 		strlcpy(name, font->name, strlen(font->name) + 1);
    726 		ent->font->name = name;
    727 	}
    728 
    729 	TAILQ_INSERT_TAIL(&list, ent, chain);
    730 	return (ent);
    731 }
    732 
    733 int
    734 wsfont_add(struct wsdisplay_font *font, int copy)
    735 {
    736 	struct font *ent;
    737 
    738 	/* Don't allow exact duplicates */
    739 	if (wsfont_find(font->name, font->fontwidth, font->fontheight,
    740 	    font->stride, 0, 0, WSFONT_FIND_ALL) >= 0)
    741 		return (EEXIST);
    742 
    743 	ent = wsfont_add0(font, copy);
    744 
    745 	ident += (1 << WSFONT_IDENT_SHIFT);
    746 	ent->cookie = wsfont_make_cookie(ident, font->bitorder,
    747 	    font->byteorder);
    748 
    749 	return (0);
    750 }
    751 
    752 int
    753 wsfont_remove(int cookie)
    754 {
    755 	struct font *ent;
    756 
    757 	if ((ent = wsfont_find0(cookie, 0xffffffff)) == NULL)
    758 		return (ENOENT);
    759 
    760 	if ((ent->flags & WSFONT_BUILTIN) != 0 || ent->lockcount != 0)
    761 		return (EBUSY);
    762 
    763 	if ((ent->flags & WSFONT_STATIC) == 0) {
    764 		free(ent->font->data, M_DEVBUF);
    765 		free(__UNCONST(ent->font->name), M_DEVBUF); /*XXXUNCONST*/
    766 		free(ent->font, M_DEVBUF);
    767 	}
    768 
    769 	TAILQ_REMOVE(&list, ent, chain);
    770 	free(ent, M_DEVBUF);
    771 
    772 	return (0);
    773 }
    774 
    775 int
    776 wsfont_lock(int cookie, struct wsdisplay_font **ptr)
    777 {
    778 	struct font *ent, *neu;
    779 	int bito, byteo;
    780 
    781 	if ((ent = wsfont_find0(cookie, 0xffffffff)) == NULL) {
    782 		if ((ent = wsfont_find0(cookie, WSFONT_IDENT_MASK)) == NULL)
    783 			return (ENOENT);
    784 
    785 		bito = (cookie & WSFONT_BITO_MASK) >> WSFONT_BITO_SHIFT;
    786 		byteo = (cookie & WSFONT_BYTEO_MASK) >> WSFONT_BYTEO_SHIFT;
    787 
    788 		if (ent->lockcount != 0) {
    789 			neu = wsfont_add0(ent->font, 1);
    790 			neu->flags |= WSFONT_COPY;
    791 
    792 			aprint_debug("wsfont: font '%s' bito %d byteo %d "
    793 			    "copied to bito %d byteo %d\n",
    794 			    ent->font->name,
    795 			    ent->font->bitorder, ent->font->byteorder,
    796 			    bito, byteo);
    797 
    798 			ent = neu;
    799 		}
    800 
    801 		if (bito && bito != ent->font->bitorder) {
    802 			wsfont_revbit(ent->font);
    803 			ent->font->bitorder = bito;
    804 		}
    805 
    806 		if (byteo && byteo != ent->font->byteorder) {
    807 			wsfont_revbyte(ent->font);
    808 			ent->font->byteorder = byteo;
    809 		}
    810 
    811 		ent->cookie = cookie;
    812 	}
    813 
    814 	ent->lockcount++;
    815 	*ptr = ent->font;
    816 	return (0);
    817 }
    818 
    819 int
    820 wsfont_unlock(int cookie)
    821 {
    822 	struct font *ent;
    823 
    824 	if ((ent = wsfont_find0(cookie, 0xffffffff)) == NULL)
    825 		return (ENOENT);
    826 
    827 	if (ent->lockcount == 0)
    828 		panic("wsfont_unlock: font not locked");
    829 
    830 	if (--ent->lockcount == 0 && (ent->flags & WSFONT_COPY) != 0)
    831 		wsfont_remove(cookie);
    832 
    833 	return (0);
    834 }
    835 
    836 /*
    837  * Unicode to font encoding mappings
    838  */
    839 
    840 /*
    841  * To save memory, font encoding tables use a two level lookup.  First the
    842  * high byte of the Unicode is used to lookup the level 2 table, then the
    843  * low byte indexes that table.  Level 2 tables that are not needed are
    844  * omitted (NULL), and both level 1 and level 2 tables have base and size
    845  * attributes to keep their size down.
    846  */
    847 
    848 struct wsfont_level1_glyphmap {
    849 	const struct	wsfont_level2_glyphmap **level2;
    850 	int	base;	/* High byte for first level2 entry	*/
    851 	int	size;	/* Number of level2 entries		*/
    852 };
    853 
    854 struct wsfont_level2_glyphmap {
    855 	int	base;	/* Low byte for first character		*/
    856 	int	size;	/* Number of characters			*/
    857 	const void	*chars;	/* Pointer to character number entries  */
    858 	int	width;	/* Size of each entry in bytes (1,2,4)  */
    859 };
    860 
    861 #define null16			\
    862 	NULL, NULL, NULL, NULL,	\
    863 	NULL, NULL, NULL, NULL,	\
    864 	NULL, NULL, NULL, NULL,	\
    865 	NULL, NULL, NULL, NULL
    866 
    867 /*
    868  * IBM 437 maps
    869  */
    870 
    871 static const u_int8_t ibm437_chars_0[] = {
    872 	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
    873 	16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
    874 	32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
    875 	48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
    876 	64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
    877 	80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
    878 	96, 97, 98, 99, 100,101,102,103,104,105,106,107,108,109,110,111,
    879 	112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
    880 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    881 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    882 	255,173,155,156, 0, 157, 0,  0,  0,  0, 166,174,170, 0,  0,  0,
    883 	 0, 241,253, 0,  0,  0,  0, 249, 0,  0, 167,175,172,171, 0, 168,
    884 	 0,  0,  0,  0, 142,143,146,128, 0, 144, 0,  0,  0,  0,  0,  0,
    885 	 0, 165, 0,  0,  0,  0, 153, 0,  0,  0,  0,  0, 154, 0,  0,  0,
    886 	133,160,131, 0, 132,134,145,135,138,130,136,137,141,161,140,139,
    887 	 0, 164,149,162,147, 0, 148,246, 0, 151,163,150,129, 0,  0, 152
    888 };
    889 
    890 static const u_int8_t ibm437_chars_1[] = {
    891 	159
    892 };
    893 
    894 static const u_int8_t ibm437_chars_3[] = {
    895 	226, 0,  0,  0,  0, 233, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    896 	228, 0,  0, 232, 0,  0, 234, 0,  0,  0,  0,  0,  0,  0, 224,225,
    897 	 0, 235,238, 0,  0,  0,  0,  0,  0, 230, 0,  0,  0, 227, 0,  0,
    898 	229,231
    899 };
    900 
    901 static const u_int8_t ibm437_chars_32[] = {
    902 	252, 0,  0,  0,  0,  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,  0,  0,  0,  0,  0, 158
    905 };
    906 
    907 static const u_int8_t ibm437_chars_34[] = {
    908 	237, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    909 	 0,  0,  0, 248,250,251, 0,  0,  0, 236, 0,  0,  0,  0,  0,  0,
    910 	 0,  0,  0,  0, 239, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    911 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    912 	 0,  0,  0, 247, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    913 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,240,  0,  0,243,
    914 	242
    915 };
    916 
    917 static const u_int8_t ibm437_chars_35[] = {
    918 	169, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    919 	244,245
    920 };
    921 
    922 static const u_int8_t ibm437_chars_37[] = {
    923 	196,205,179,186, 0,  0,  0,  0,  0,  0,  0,  0, 218,213,214,201,
    924 	191,184,183,187,192,212,211,200,217,190,189,188,195,198, 0,  0,
    925 	199, 0,  0, 204,180,181, 0,  0, 182, 0,  0, 185,194, 0,  0, 209,
    926 	210, 0,  0, 203,193, 0,  0, 207,208, 0,  0, 202,197, 0,  0, 216,
    927 	 0,  0, 215, 0,  0,  0,  0,  0,  0,  0,  0, 206, 0,  0,  0,  0,
    928 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    929 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    930 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    931 	223, 0,  0,  0, 220, 0,  0,  0, 219, 0,  0,  0, 221, 0,  0,  0,
    932 	222,176,177,178, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    933 	254
    934 };
    935 
    936 static const struct wsfont_level2_glyphmap ibm437_level2_0 =
    937     { 0, 256, ibm437_chars_0, 1 };
    938 
    939 static const struct wsfont_level2_glyphmap ibm437_level2_1 =
    940     { 146, 1, ibm437_chars_1, 1 };
    941 
    942 static const struct wsfont_level2_glyphmap ibm437_level2_3 =
    943     { 147, 50, ibm437_chars_3, 1 };
    944 
    945 static const struct wsfont_level2_glyphmap ibm437_level2_32 =
    946     { 127, 41, ibm437_chars_32, 1 };
    947 
    948 static const struct wsfont_level2_glyphmap ibm437_level2_34 =
    949     { 5, 97, ibm437_chars_34, 1 };
    950 
    951 static const struct wsfont_level2_glyphmap ibm437_level2_35 =
    952     { 16, 18, ibm437_chars_35, 1 };
    953 
    954 static const struct wsfont_level2_glyphmap ibm437_level2_37 =
    955     { 0, 161, ibm437_chars_37, 1 };
    956 
    957 static const struct wsfont_level2_glyphmap *ibm437_level1[] = {
    958 	&ibm437_level2_0, &ibm437_level2_1, NULL, &ibm437_level2_3,
    959 	NULL, NULL, NULL, NULL,
    960 	NULL, NULL, NULL, NULL,
    961 	NULL, NULL, NULL, NULL,
    962 	NULL, NULL, NULL, NULL,
    963 	NULL, NULL, NULL, NULL,
    964 	NULL, NULL, NULL, NULL,
    965 	NULL, NULL, NULL, NULL,
    966 	&ibm437_level2_32, NULL, &ibm437_level2_34, &ibm437_level2_35,
    967 	NULL, &ibm437_level2_37
    968 };
    969 
    970 /*
    971  * ISO-8859-7 maps
    972  */
    973 static const u_int8_t iso7_chars_0[] = {
    974 	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
    975 	16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
    976 	32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
    977 	48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
    978 	64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
    979 	80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
    980 	96, 97, 98, 99, 100,101,102,103,104,105,106,107,108,109,110,111,
    981 	112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
    982 	128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
    983 	144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
    984 	160, 0,  0, 163, 0,  0, 166,167,168,169, 0, 171,172,173, 0,  0,
    985 	176,177,178,179,180, 0,  0, 183, 0,  0,  0, 187, 0, 189
    986 };
    987 
    988 static const u_int8_t iso7_chars_3[] = {
    989 	182, 0, 184,185,186, 0, 188, 0, 190,191,192,193,194,195,196,197,
    990 	198,199,200,201,202,203,204,205,206,207,208,209, 0, 211,212,213,
    991 	214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,
    992 	230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,
    993 	246,247,248,249,250,251,252,253,254, 0,  0,  0,  0,  0,  0,  0,
    994 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    995 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 181
    996 };
    997 
    998 /*
    999  * map all variants of the box drawing characters to the same basic shapes for
   1000  * now, encoded like this:
   1001  *
   1002  *    1
   1003  *    1
   1004  * 888 222
   1005  *    4
   1006  *    4
   1007  *
   1008  * so an upright line would be 0x05
   1009  */
   1010 #define FL |WSFONT_FLAG_OPT
   1011 static const u_int32_t netbsd_boxes[] = {
   1012 /*00*/ 0x0a FL, 0x0a FL, 0x05 FL, 0x05 FL, 0x0a FL, 0x0a FL, 0x05 FL, 0x05 FL,
   1013 /*08*/ 0x0a FL, 0x0a FL, 0x05 FL, 0x05 FL, 0x06 FL, 0x06 FL, 0x06 FL, 0x06 FL,
   1014 /*10*/ 0x0c FL, 0x0c FL, 0x0c FL, 0x0c FL, 0x03 FL, 0x03 FL, 0x03 FL, 0x03 FL,
   1015 /*18*/ 0x09 FL, 0x09 FL, 0x09 FL, 0x09 FL, 0x07 FL, 0x07 FL, 0x07 FL, 0x07 FL,
   1016 /*20*/ 0x07 FL, 0x07 FL, 0x07 FL, 0x07 FL, 0x0d FL, 0x0d FL, 0x0d FL, 0x0d FL,
   1017 /*28*/ 0x0d FL, 0x0d FL, 0x0d FL, 0x0d FL, 0x0e FL, 0x0e FL, 0x0e FL, 0x0e FL,
   1018 /*30*/ 0x0e FL, 0x0e FL, 0x0e FL, 0x0e FL, 0x0b FL, 0x0b FL, 0x0b FL, 0x0b FL,
   1019 /*38*/ 0x0b FL, 0x0b FL, 0x0b FL, 0x0b FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL,
   1020 /*40*/ 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL,
   1021 /*48*/ 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0a FL, 0x0a FL, 0x05 FL, 0x05 FL,
   1022 /*50*/ 0x0a FL, 0x05 FL, 0x06 FL, 0x06 FL, 0x06 FL, 0x0c FL, 0x0c FL, 0x0c FL,
   1023 /*58*/ 0x03 FL, 0x03 FL, 0x03 FL, 0x09 FL, 0x09 FL, 0x09 FL, 0x07 FL, 0x07 FL,
   1024 /*60*/ 0x07 FL, 0x0d FL, 0x0d FL, 0x0d FL, 0x0e FL, 0x0e FL, 0x0e FL, 0x0b FL,
   1025 /*68*/ 0x0b FL, 0x0b FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x06 FL, 0x0c FL, 0x09 FL,
   1026 /*70*/ 0x03 FL,    0 FL,    0 FL,    0 FL, 0x08 FL, 0x01 FL, 0x02 FL, 0x04 FL,
   1027 /*78*/ 0x08 FL, 0x01 FL, 0x02 FL, 0x04 FL, 0x0a FL, 0x05 FL, 0x0a FL, 0x05 FL
   1028 };
   1029 #undef FL
   1030 
   1031 static const u_int8_t iso7_chars_32[] = {
   1032 	175, 0,  0,  0,  0, 162, 0, 161
   1033 };
   1034 
   1035 static const struct wsfont_level2_glyphmap iso7_level2_0 =
   1036     { 0, 190, iso7_chars_0, 1 };
   1037 
   1038 static const struct wsfont_level2_glyphmap iso7_level2_3 =
   1039     { 134, 111, iso7_chars_3, 1 };
   1040 
   1041 static const struct wsfont_level2_glyphmap iso7_level2_32 =
   1042     { 20, 8, iso7_chars_32, 1 };
   1043 
   1044 static const struct wsfont_level2_glyphmap netbsd_box_drawing =
   1045     { 0, 128, netbsd_boxes, 4 };
   1046 
   1047 static const struct wsfont_level2_glyphmap *iso7_level1[] = {
   1048 	&iso7_level2_0, NULL, NULL, &iso7_level2_3,
   1049 	NULL, NULL, NULL, NULL,
   1050 	NULL, NULL, NULL, NULL,
   1051 	NULL, NULL, NULL, NULL,
   1052 	NULL, NULL, NULL, NULL,
   1053 	NULL, NULL, NULL, NULL,
   1054 	NULL, NULL, NULL, NULL,
   1055 	NULL, NULL, NULL, NULL,
   1056 	&iso7_level2_32, NULL, NULL, NULL,
   1057 	NULL, &netbsd_box_drawing
   1058 };
   1059 
   1060 static const struct wsfont_level2_glyphmap *iso_level1[] = {
   1061 	NULL, NULL, NULL, NULL,
   1062 	NULL, NULL, NULL, NULL,
   1063 	NULL, NULL, NULL, NULL,
   1064 	NULL, NULL, NULL, NULL,
   1065 	NULL, NULL, NULL, NULL,
   1066 	NULL, NULL, NULL, NULL,
   1067 	NULL, NULL, NULL, NULL,
   1068 	NULL, NULL, NULL, NULL,
   1069 	NULL, NULL, NULL, NULL,
   1070 	NULL, &netbsd_box_drawing
   1071 };
   1072 
   1073 static const struct wsfont_level1_glyphmap encodings[] = {
   1074 	{ iso_level1, 0, 0x26 },	/* WSDISPLAY_FONTENC_ISO */
   1075 	{ ibm437_level1, 0, 38 },	/* WSDISPLAY_FONTENC_IBM */
   1076 	{ NULL, 0, 0 },			/* WSDISPLAY_FONTENC_PCVT */
   1077 	{ iso7_level1, 0, 0x26 },	/* WSDISPLAY_FONTENC_ISO7 */
   1078 };
   1079 
   1080 #define MAX_ENCODING (sizeof(encodings) / sizeof(encodings[0]))
   1081 
   1082 /*
   1083  * Remap Unicode character to glyph
   1084  */
   1085 int
   1086 wsfont_map_unichar(struct wsdisplay_font *font, int c)
   1087 {
   1088 	const struct wsfont_level1_glyphmap *map1;
   1089 	const struct wsfont_level2_glyphmap *map2;
   1090 	int hi, lo;
   1091 
   1092 	if (font->encoding < 0 || font->encoding >= MAX_ENCODING)
   1093 		return (-1);
   1094 
   1095 	hi = (c >> 8);
   1096 	lo = c & 255;
   1097 	map1 = &encodings[font->encoding];
   1098 
   1099 	if (hi < map1->base || hi >= map1->base + map1->size)
   1100 		return (-1);
   1101 
   1102 	map2 = map1->level2[hi - map1->base];
   1103 
   1104 	/* so we don't need an identical level 2 table for hi == 0 */
   1105 	if (hi == 0 && font->encoding == WSDISPLAY_FONTENC_ISO)
   1106 		return lo;
   1107 
   1108 	if (map2 == NULL || lo < map2->base || lo >= map2->base + map2->size)
   1109 		return (-1);
   1110 
   1111 	lo -= map2->base;
   1112 
   1113 	switch(map2->width) {
   1114 	case 1:
   1115 		c = (((const u_int8_t *)map2->chars)[lo]);
   1116 		break;
   1117 	case 2:
   1118 		c = (((const u_int16_t *)map2->chars)[lo]);
   1119 		break;
   1120 	case 4:
   1121 		c = (((const u_int32_t *)map2->chars)[lo]);
   1122 		break;
   1123 	}
   1124 
   1125 	if (c == 0 && lo != 0)
   1126 		return (-1);
   1127 
   1128 	return (c);
   1129 }
   1130