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