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