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