1 /* $OpenBSD: wsfont.c,v 1.65 2023/10/24 13:52:49 fcambus Exp $ */ 2 /* $NetBSD: wsfont.c,v 1.17 2001/02/07 13:59:24 ad Exp $ */ 3 4 /*- 5 * Copyright (c) 1999 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Andrew Doran. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/time.h> 36 #include <sys/malloc.h> 37 #include <sys/queue.h> 38 39 #include <dev/wscons/wsconsio.h> 40 #include <dev/wsfont/wsfont.h> 41 42 #include "wsfont_glue.h" /* NRASOPS_ROTATION */ 43 44 #undef HAVE_FONT 45 46 #ifdef FONT_SPLEEN5x8 47 #define HAVE_FONT 1 48 #include <dev/wsfont/spleen5x8.h> 49 #endif 50 51 #ifdef FONT_SPLEEN6x12 52 #define HAVE_FONT 1 53 #include <dev/wsfont/spleen6x12.h> 54 #endif 55 56 #ifdef FONT_SPLEEN8x16_IBM 57 #define HAVE_FONT 1 58 #include <dev/wsfont/spleen8x16-ibm.h> 59 #endif 60 61 #ifdef FONT_SPLEEN8x16 62 #define HAVE_FONT 1 63 #endif 64 65 #ifdef FONT_SPLEEN12x24 66 #define HAVE_FONT 1 67 #endif 68 69 #ifdef FONT_SPLEEN16x32 70 #define HAVE_FONT 1 71 #endif 72 73 #ifdef FONT_SPLEEN32x64 74 #define HAVE_FONT 1 75 #endif 76 77 #ifdef FONT_GALLANT12x22 78 #define HAVE_FONT 1 79 #endif 80 81 /* 82 * Make sure we always have at least one font. 83 * Unless otherwise configured, all platforms provide both a 8x16 font and a 84 * larger 12x22 font. 85 * Some platforms will however only provide the 8x16 font if option 86 * SMALL_KERNEL. 87 */ 88 #ifndef HAVE_FONT 89 #define HAVE_FONT 1 90 91 #define FONT_SPLEEN8x16 92 #if defined(__sparc64__) 93 #define FONT_GALLANT12x22 94 #elif defined(__alpha__) || defined(__luna88k__) || defined(__macppc__) || \ 95 !defined(SMALL_KERNEL) 96 #define FONT_SPLEEN12x24 97 #endif 98 99 #if !defined(SMALL_KERNEL) && (defined(__amd64__) || defined(__i386__) || \ 100 defined(__arm64__) || defined(__armv7__) || defined(__riscv64__) || \ 101 defined(__powerpc64__)) 102 #define FONT_SPLEEN16x32 103 #define FONT_SPLEEN32x64 104 #endif 105 106 #endif /* HAVE_FONT */ 107 108 #ifdef FONT_GALLANT12x22 109 #include <dev/wsfont/gallant12x22.h> 110 #endif 111 112 #ifdef FONT_SPLEEN8x16 113 #include <dev/wsfont/spleen8x16.h> 114 #endif 115 116 #ifdef FONT_SPLEEN12x24 117 #include <dev/wsfont/spleen12x24.h> 118 #endif 119 120 #ifdef FONT_SPLEEN16x32 121 #include <dev/wsfont/spleen16x32.h> 122 #endif 123 124 #ifdef FONT_SPLEEN32x64 125 #include <dev/wsfont/spleen32x64.h> 126 #endif 127 128 struct font { 129 TAILQ_ENTRY(font) chain; 130 struct wsdisplay_font *font; 131 u_short lockcount; 132 u_short cookie; 133 u_short flg; 134 }; 135 TAILQ_HEAD(, font) fontlist; 136 137 /* Our list of built-in fonts */ 138 static struct font builtin_fonts[] = { 139 #define BUILTIN_FONT(f, c) \ 140 { .font = &(f), .cookie = (c), .lockcount = 0, \ 141 .flg = WSFONT_STATIC | WSFONT_BUILTIN } 142 #ifdef FONT_GALLANT12x22 143 BUILTIN_FONT(gallant12x22, 1), 144 #endif 145 #ifdef FONT_SPLEEN5x8 146 BUILTIN_FONT(spleen5x8, 2), 147 #endif 148 #ifdef FONT_SPLEEN6x12 149 BUILTIN_FONT(spleen6x12, 3), 150 #endif 151 #ifdef FONT_SPLEEN8x16 152 BUILTIN_FONT(spleen8x16, 4), 153 #endif 154 #ifdef FONT_SPLEEN8x16_IBM 155 BUILTIN_FONT(spleen8x16_ibm, 5), 156 #endif 157 #ifdef FONT_SPLEEN12x24 158 BUILTIN_FONT(spleen12x24, 6), 159 #endif 160 #ifdef FONT_SPLEEN16x32 161 BUILTIN_FONT(spleen16x32, 7), 162 #endif 163 #ifdef FONT_SPLEEN32x64 164 BUILTIN_FONT(spleen32x64, 8), 165 #endif 166 #undef BUILTIN_FONT 167 }; 168 169 #if !defined(SMALL_KERNEL) || defined(__alpha__) 170 #define INCLUDE_FONT_BIT_ENDIANNESS_SWAP_CODE 171 #endif 172 173 #ifdef INCLUDE_FONT_BIT_ENDIANNESS_SWAP_CODE 174 175 /* Reverse the bit order in a byte */ 176 static const u_char reverse[256] = { 177 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 178 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, 179 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 180 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 181 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 182 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 183 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 184 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 185 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 186 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 187 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 188 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 189 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 190 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, 191 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 192 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 193 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 194 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 195 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 196 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 197 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 198 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 199 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 200 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 201 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 202 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 203 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 204 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 205 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 206 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 207 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 208 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, 209 }; 210 211 #endif 212 213 static struct font *wsfont_find0(int); 214 215 #ifdef INCLUDE_FONT_BIT_ENDIANNESS_SWAP_CODE 216 217 /* 218 * Reverse the bit order of a font 219 */ 220 static void wsfont_revbit(struct wsdisplay_font *); 221 static void 222 wsfont_revbit(struct wsdisplay_font *font) 223 { 224 u_char *p, *m; 225 226 p = (u_char *)font->data; 227 m = p + font->stride * font->numchars * font->fontheight; 228 229 for (; p < m; p++) 230 *p = reverse[*p]; 231 } 232 233 #endif 234 235 #if !defined(SMALL_KERNEL) 236 237 /* 238 * Reverse the byte order of a font 239 */ 240 static void wsfont_revbyte(struct wsdisplay_font *); 241 static void 242 wsfont_revbyte(struct wsdisplay_font *font) 243 { 244 int x, l, r, nr; 245 u_char *rp; 246 247 if (font->stride == 1) 248 return; 249 250 rp = (u_char *)font->data; 251 nr = font->numchars * font->fontheight; 252 253 while (nr--) { 254 l = 0; 255 r = font->stride - 1; 256 257 while (l < r) { 258 x = rp[l]; 259 rp[l] = rp[r]; 260 rp[r] = x; 261 l++, r--; 262 } 263 264 rp += font->stride; 265 } 266 } 267 268 #endif 269 270 /* 271 * Enumerate the list of fonts 272 */ 273 void 274 wsfont_enum(int (*cb)(void *, struct wsdisplay_font *), void *cbarg) 275 { 276 struct font *ent; 277 int s; 278 279 s = splhigh(); 280 281 TAILQ_FOREACH(ent, &fontlist, chain) 282 if (cb(cbarg, ent->font) != 0) 283 break; 284 285 splx(s); 286 } 287 288 #if NRASOPS_ROTATION > 0 289 290 void wsfont_rotate_cw(struct wsdisplay_font *, char *, int); 291 void wsfont_rotate_ccw(struct wsdisplay_font *, char *, int); 292 struct wsdisplay_font *wsfont_rotate_internal(struct wsdisplay_font *, int); 293 294 void 295 wsfont_rotate_cw(struct wsdisplay_font *font, char *newbits, int newstride) 296 { 297 int b, n, r; 298 299 /* Rotate the font a bit at a time. */ 300 for (n = 0; n < font->numchars; n++) { 301 char *ch = font->data + (n * font->stride * font->fontheight); 302 303 for (r = 0; r < font->fontheight; r++) { 304 for (b = 0; b < font->fontwidth; b++) { 305 unsigned char *rb; 306 307 rb = ch + (font->stride * r) + (b / 8); 308 if (*rb & (0x80 >> (b % 8))) { 309 unsigned char *rrb; 310 311 rrb = newbits + newstride - 1 - (r / 8) 312 + (n * newstride * font->fontwidth) 313 + (newstride * b); 314 *rrb |= (1 << (r % 8)); 315 } 316 } 317 } 318 } 319 } 320 321 void 322 wsfont_rotate_ccw(struct wsdisplay_font *font, char *newbits, int newstride) 323 { 324 int b, n, r; 325 326 /* Rotate the font a bit at a time. */ 327 for (n = 0; n < font->numchars; n++) { 328 char *ch = font->data + (n * font->stride * font->fontheight); 329 330 for (r = 0; r < font->fontheight; r++) { 331 for (b = 0; b < font->fontwidth; b++) { 332 int bb = font->fontwidth - 1 - b; 333 unsigned char *rb; 334 335 rb = ch + (font->stride * r) + (b / 8); 336 if (*rb & (0x80 >> (b % 8))) { 337 unsigned char *rrb; 338 339 rrb = newbits + (r / 8) 340 + (n * newstride * font->fontwidth) 341 + (newstride * bb); 342 *rrb |= (1 << (7 - (r % 8))); 343 } 344 } 345 } 346 } 347 } 348 349 struct wsdisplay_font * 350 wsfont_rotate_internal(struct wsdisplay_font *font, int ccw) 351 { 352 int newstride; 353 struct wsdisplay_font *newfont; 354 char *newbits; 355 356 /* Duplicate the existing font... */ 357 newfont = malloc(sizeof *font, M_DEVBUF, M_WAITOK); 358 359 bcopy(font, newfont, sizeof *font); 360 newfont->cookie = NULL; 361 362 /* Allocate a buffer big enough for the rotated font. */ 363 newstride = (font->fontheight + 7) / 8; 364 newbits = mallocarray(font->numchars, newstride * font->fontwidth, 365 M_DEVBUF, M_WAITOK | M_ZERO); 366 367 if (ccw) 368 wsfont_rotate_ccw(font, newbits, newstride); 369 else 370 wsfont_rotate_cw(font, newbits, newstride); 371 372 newfont->data = newbits; 373 374 /* Update font sizes. */ 375 newfont->stride = newstride; 376 newfont->fontwidth = font->fontheight; 377 newfont->fontheight = font->fontwidth; 378 379 if (wsfont_add(newfont, 0) != 0) { 380 /* 381 * If we seem to have rotated this font already, drop the 382 * new one... 383 */ 384 free(newbits, M_DEVBUF, 385 font->numchars * newstride * font->fontwidth); 386 free(newfont, M_DEVBUF, sizeof *font); 387 newfont = NULL; 388 } 389 390 return (newfont); 391 } 392 393 int 394 wsfont_rotate(int cookie, int ccw) 395 { 396 int s, ncookie; 397 struct wsdisplay_font *font; 398 struct font *origfont; 399 400 s = splhigh(); 401 origfont = wsfont_find0(cookie); 402 splx(s); 403 404 font = wsfont_rotate_internal(origfont->font, ccw); 405 if (font == NULL) 406 return (-1); 407 408 ncookie = wsfont_find(font->name, font->fontwidth, font->fontheight, 409 font->stride); 410 411 return (ncookie); 412 } 413 414 #endif /* NRASOPS_ROTATION */ 415 416 /* 417 * Initialize list with WSFONT_BUILTIN fonts 418 */ 419 void 420 wsfont_init(void) 421 { 422 static int again; 423 unsigned int i; 424 425 if (again != 0) 426 return; 427 again = 1; 428 429 TAILQ_INIT(&fontlist); 430 431 for (i = 0; i < nitems(builtin_fonts); i++) { 432 TAILQ_INSERT_TAIL(&fontlist, &builtin_fonts[i], chain); 433 } 434 } 435 436 /* 437 * Find a font by cookie. Called at splhigh. 438 */ 439 static struct font * 440 wsfont_find0(int cookie) 441 { 442 struct font *ent; 443 444 TAILQ_FOREACH(ent, &fontlist, chain) 445 if (ent->cookie == cookie) 446 return (ent); 447 448 return (NULL); 449 } 450 451 /* 452 * Find a font. 453 */ 454 int 455 wsfont_find(const char *name, int width, int height, int stride) 456 { 457 struct font *ent; 458 int s; 459 460 s = splhigh(); 461 462 TAILQ_FOREACH(ent, &fontlist, chain) { 463 if (height != 0 && ent->font->fontheight != height) 464 continue; 465 466 if (width != 0 && ent->font->fontwidth != width) 467 continue; 468 469 if (stride != 0 && ent->font->stride != stride) 470 continue; 471 472 if (name != NULL && strcmp(ent->font->name, name) != 0) 473 continue; 474 475 splx(s); 476 return (ent->cookie); 477 } 478 479 splx(s); 480 return (-1); 481 } 482 483 /* 484 * Add a font to the list. 485 */ 486 int 487 wsfont_add(struct wsdisplay_font *font, int copy) 488 { 489 static int cookiegen = 666; 490 struct font *ent; 491 int s, fontc = 0; 492 493 s = splhigh(); 494 495 /* Don't allow exact duplicates */ 496 if (wsfont_find(font->name, font->fontwidth, font->fontheight, 497 font->stride) >= 0) { 498 splx(s); 499 return (-1); 500 } 501 502 TAILQ_FOREACH(ent, &fontlist, chain) 503 fontc++; 504 505 if (fontc >= WSDISPLAY_MAXFONTCOUNT) { 506 splx(s); 507 return (-1); 508 } 509 510 ent = (struct font *)malloc(sizeof *ent, M_DEVBUF, M_WAITOK); 511 512 ent->lockcount = 0; 513 ent->flg = 0; 514 ent->cookie = cookiegen++; 515 516 /* 517 * If we are coming from a WSDISPLAYIO_LDFONT ioctl, we need to 518 * make a copy of the wsdisplay_font struct, but not of font->bits. 519 */ 520 if (copy) { 521 ent->font = (struct wsdisplay_font *)malloc(sizeof *ent->font, 522 M_DEVBUF, M_WAITOK); 523 memcpy(ent->font, font, sizeof(*ent->font)); 524 ent->flg = 0; 525 } else { 526 ent->font = font; 527 ent->flg = WSFONT_STATIC; 528 } 529 530 /* Now link into the list and return */ 531 TAILQ_INSERT_TAIL(&fontlist, ent, chain); 532 splx(s); 533 return (0); 534 } 535 536 /* 537 * Lock a given font and return new lockcount. This fails if the cookie 538 * is invalid, or if the font is already locked and the bit/byte order 539 * requested by the caller differs. 540 */ 541 int 542 wsfont_lock(int cookie, struct wsdisplay_font **ptr, int bitorder, 543 int byteorder) 544 { 545 struct font *ent; 546 int s, lc; 547 548 s = splhigh(); 549 550 if ((ent = wsfont_find0(cookie)) != NULL) { 551 if (bitorder && bitorder != ent->font->bitorder) { 552 #ifdef INCLUDE_FONT_BIT_ENDIANNESS_SWAP_CODE 553 if (ent->lockcount) { 554 splx(s); 555 return (-1); 556 } 557 wsfont_revbit(ent->font); 558 ent->font->bitorder = bitorder; 559 #else 560 splx(s); 561 return (-1); 562 #endif 563 } 564 565 if (byteorder && byteorder != ent->font->byteorder) { 566 #if !defined(SMALL_KERNEL) 567 if (ent->lockcount) { 568 splx(s); 569 return (-1); 570 } 571 wsfont_revbyte(ent->font); 572 ent->font->byteorder = byteorder; 573 #else 574 splx(s); 575 return (-1); 576 #endif 577 } 578 579 lc = ++ent->lockcount; 580 *ptr = ent->font; 581 } else 582 lc = -1; 583 584 splx(s); 585 return (lc); 586 } 587 588 /* 589 * Unlock a given font and return new lockcount. 590 */ 591 int 592 wsfont_unlock(int cookie) 593 { 594 struct font *ent; 595 int s, lc; 596 597 s = splhigh(); 598 599 if ((ent = wsfont_find0(cookie)) != NULL) { 600 if (ent->lockcount == 0) 601 panic("wsfont_unlock: font not locked"); 602 lc = --ent->lockcount; 603 } else 604 lc = -1; 605 606 splx(s); 607 return (lc); 608 } 609 610 #if !defined(SMALL_KERNEL) 611 612 /* 613 * Unicode to font encoding mappings 614 */ 615 616 /* 617 * To save memory, font encoding tables use a two level lookup. 618 * First the high byte of the Unicode is used to lookup the level 2 619 * table, then the low byte indexes that table. Level 2 tables that are 620 * not needed are omitted (NULL), and both level 1 and level 2 tables 621 * have base and size attributes to keep their size down. 622 */ 623 624 struct wsfont_level1_glyphmap { 625 const struct wsfont_level2_glyphmap **level2; 626 int base; /* High byte for first level2 entry */ 627 int size; /* Number of level2 entries */ 628 }; 629 630 struct wsfont_level2_glyphmap { 631 int base; /* Low byte for first character */ 632 int size; /* Number of characters */ 633 const void *chars; /* Pointer to character number entries */ 634 int width; /* Size of each entry in bytes (1,2,4) */ 635 }; 636 637 /* 638 * IBM 437 maps 639 */ 640 641 static const u_int8_t 642 ibm437_chars_0[] = { 643 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 644 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 645 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 646 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 647 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 648 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 649 96, 97, 98, 99, 100,101,102,103,104,105,106,107,108,109,110,111, 650 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, 651 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 652 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 653 255,173,155,156, 0, 157, 0, 0, 0, 0, 166,174,170, 0, 0, 0, 654 0, 241,253, 0, 0, 0, 0, 249, 0, 0, 167,175,172,171, 0, 168, 655 0, 0, 0, 0, 142,143,146,128, 0, 144, 0, 0, 0, 0, 0, 0, 656 0, 165, 0, 0, 0, 0, 153, 0, 0, 0, 0, 0, 154, 0, 0, 0, 657 133,160,131, 0, 132,134,145,135,138,130,136,137,141,161,140,139, 658 0, 164,149,162,147, 0, 148,246, 0, 151,163,150,129, 0, 0, 152 659 }, 660 ibm437_chars_1[] = { 661 159 662 }, 663 ibm437_chars_3[] = { 664 226, 0, 0, 0, 0, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 665 228, 0, 0, 232, 0, 0, 234, 0, 0, 0, 0, 0, 0, 0, 224,225, 666 0, 235,238, 0, 0, 0, 0, 0, 0, 230, 0, 0, 0, 227, 0, 0, 667 229,231 668 }, 669 ibm437_chars_32[] = { 670 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 671 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 672 0, 0, 0, 0, 0, 0, 0, 0, 158 673 }, 674 ibm437_chars_34[] = { 675 237, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 676 0, 0, 0, 248,250,251, 0, 0, 0, 236, 0, 0, 0, 0, 0, 0, 677 0, 0, 0, 0, 239, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 678 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 679 0, 0, 0, 247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 680 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 0, 0,243, 681 242 682 }, 683 ibm437_chars_35[] = { 684 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 685 244,245 686 }, 687 ibm437_chars_37[] = { 688 196,205,179,186, 0, 0, 0, 0, 0, 0, 0, 0, 218,213,214,201, 689 191,184,183,187,192,212,211,200,217,190,189,188,195,198, 0, 0, 690 199, 0, 0, 204,180,181, 0, 0, 182, 0, 0, 185,194, 0, 0, 209, 691 210, 0, 0, 203,193, 0, 0, 207,208, 0, 0, 202,197, 0, 0, 216, 692 0, 0, 215, 0, 0, 0, 0, 0, 0, 0, 0, 206, 0, 0, 0, 0, 693 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 694 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 695 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 696 223, 0, 0, 0, 220, 0, 0, 0, 219, 0, 0, 0, 221, 0, 0, 0, 697 222,176,177,178, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 698 254 699 }; 700 701 static const struct wsfont_level2_glyphmap 702 ibm437_level2_0 = { 0, 256, ibm437_chars_0, 1 }, 703 ibm437_level2_1 = { 146, 1, ibm437_chars_1, 1 }, 704 ibm437_level2_3 = { 147, 50, ibm437_chars_3, 1 }, 705 ibm437_level2_32 = { 127, 41, ibm437_chars_32, 1 }, 706 ibm437_level2_34 = { 5, 97, ibm437_chars_34, 1 }, 707 ibm437_level2_35 = { 16, 18, ibm437_chars_35, 1 }, 708 ibm437_level2_37 = { 0, 161, ibm437_chars_37, 1 }; 709 710 static const struct wsfont_level2_glyphmap *ibm437_level1[] = { 711 &ibm437_level2_0, &ibm437_level2_1, NULL, &ibm437_level2_3, 712 NULL, NULL, NULL, NULL, 713 NULL, NULL, NULL, NULL, 714 NULL, NULL, NULL, NULL, 715 NULL, NULL, NULL, NULL, 716 NULL, NULL, NULL, NULL, 717 NULL, NULL, NULL, NULL, 718 NULL, NULL, NULL, NULL, 719 &ibm437_level2_32, NULL, &ibm437_level2_34, &ibm437_level2_35, 720 NULL, &ibm437_level2_37 721 }; 722 723 static const struct wsfont_level1_glyphmap encodings[] = { 724 /* WSDISPLAY_FONTENC_ISO */ 725 { NULL, 0, 0 }, 726 /* WSDISPLAY_FONTENC_IBM */ 727 { ibm437_level1, 0, nitems(ibm437_level1) } 728 }; 729 730 #endif /* !SMALL_KERNEL */ 731 732 /* 733 * Remap Unicode character to glyph 734 */ 735 int 736 wsfont_map_unichar(struct wsdisplay_font *font, int c) 737 { 738 if (font->encoding == WSDISPLAY_FONTENC_ISO) 739 return (c); 740 741 #if !defined(SMALL_KERNEL) 742 if (font->encoding >= 0 && font->encoding < nitems(encodings)) { 743 int hi = (c >> 8), lo = c & 255; 744 const struct wsfont_level1_glyphmap *map1 = 745 &encodings[font->encoding]; 746 const struct wsfont_level2_glyphmap *map2; 747 748 hi -= map1->base; 749 750 if (hi >= 0 && hi < map1->size && 751 (map2 = map1->level2[hi]) != NULL) { 752 lo -= map2->base; 753 754 if (lo >= 0 && lo < map2->size) { 755 switch (map2->width) { 756 case 1: 757 c = (((u_int8_t *)map2->chars)[lo]); 758 break; 759 case 2: 760 c = (((u_int16_t *)map2->chars)[lo]); 761 break; 762 case 4: 763 c = (((u_int32_t *)map2->chars)[lo]); 764 break; 765 } 766 767 if (c != 0 || lo == 0) 768 return (c); 769 } 770 } 771 } 772 #endif /* !SMALL_KERNEL */ 773 774 return (-1); 775 } 776