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