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