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