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