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