1 /* $NetBSD: wsfont.c,v 1.61 2016/11/20 15:55:31 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.61 2016/11/20 15:55:31 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 #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 if (newfont == NULL) 371 return (NULL); 372 373 *newfont = *font; 374 375 namelen = strlen(font->name) + 4; 376 newname = malloc(namelen, M_DEVBUF, M_WAITOK); 377 strlcpy(newname, font->name, namelen); 378 strlcat(newname, "cw", namelen); 379 newfont->name = newname; 380 381 /* Allocate a buffer big enough for the rotated font. */ 382 newstride = (font->fontheight + 7) / 8; 383 newbits = malloc(newstride * font->fontwidth * font->numchars, 384 M_DEVBUF, M_WAITOK|M_ZERO); 385 if (newbits == NULL) { 386 free(newfont, M_DEVBUF); 387 return (NULL); 388 } 389 390 /* Rotate the font a bit at a time. */ 391 for (n = 0; n < font->numchars; n++) { 392 unsigned char *ch = (unsigned char *)font->data + 393 (n * font->stride * font->fontheight); 394 395 for (r = 0; r < font->fontheight; r++) { 396 for (b = 0; b < font->fontwidth; b++) { 397 unsigned char *rb; 398 399 rb = ch + (font->stride * r) + (b / 8); 400 if (*rb & (0x80 >> (b % 8))) { 401 unsigned char *rrb; 402 403 rrb = newbits + newstride - 1 - (r / 8) 404 + (n * newstride * font->fontwidth) 405 + (newstride * b); 406 *rrb |= (1 << (r % 8)); 407 } 408 } 409 } 410 } 411 412 newfont->data = newbits; 413 414 /* Update font sizes. */ 415 newfont->stride = newstride; 416 newfont->fontwidth = font->fontheight; 417 newfont->fontheight = font->fontwidth; 418 419 if (wsfont_add(newfont, 0) != 0) { 420 /* 421 * If we seem to have rotated this font already, drop the 422 * new one... 423 */ 424 free(newbits, M_DEVBUF); 425 free(newfont, M_DEVBUF); 426 newfont = NULL; 427 } 428 429 return (newfont); 430 } 431 432 struct wsdisplay_font * 433 wsfont_rotate_ccw_internal(struct wsdisplay_font *font) 434 { 435 int b, n, r, namelen, newstride; 436 struct wsdisplay_font *newfont; 437 char *newname, *newbits; 438 439 /* Duplicate the existing font... */ 440 newfont = malloc(sizeof(*font), M_DEVBUF, M_WAITOK); 441 if (newfont == NULL) 442 return (NULL); 443 444 *newfont = *font; 445 446 namelen = strlen(font->name) + 4; 447 newname = malloc(namelen, M_DEVBUF, M_WAITOK); 448 strlcpy(newname, font->name, namelen); 449 strlcat(newname, "ccw", namelen); 450 newfont->name = newname; 451 452 /* Allocate a buffer big enough for the rotated font. */ 453 newstride = (font->fontheight + 7) / 8; 454 newbits = malloc(newstride * font->fontwidth * font->numchars, 455 M_DEVBUF, M_WAITOK|M_ZERO); 456 if (newbits == NULL) { 457 free(newfont, M_DEVBUF); 458 return (NULL); 459 } 460 461 /* Rotate the font a bit at a time. */ 462 for (n = 0; n < font->numchars; n++) { 463 unsigned char *ch = (unsigned char *)font->data + 464 (n * font->stride * font->fontheight); 465 466 for (r = 0; r < font->fontheight; r++) { 467 for (b = 0; b < font->fontwidth; b++) { 468 unsigned char *rb; 469 470 rb = ch + (font->stride * r) + (b / 8); 471 if (*rb & (0x80 >> (b % 8))) { 472 unsigned char *rrb; 473 int w = font->fontwidth; 474 475 rrb = newbits + (r / 8) 476 + (n * newstride * w) 477 + (newstride * (w - 1 - b)); 478 *rrb |= (0x80 >> (r % 8)); 479 } 480 } 481 } 482 } 483 484 newfont->data = newbits; 485 486 /* Update font sizes. */ 487 newfont->stride = newstride; 488 newfont->fontwidth = font->fontheight; 489 newfont->fontheight = font->fontwidth; 490 491 if (wsfont_add(newfont, 0) != 0) { 492 /* 493 * If we seem to have rotated this font already, drop the 494 * new one... 495 */ 496 free(newbits, M_DEVBUF); 497 free(newfont, M_DEVBUF); 498 newfont = NULL; 499 } 500 501 return (newfont); 502 } 503 504 int 505 wsfont_rotate(int cookie, int rotate) 506 { 507 int s, ncookie; 508 struct wsdisplay_font *font; 509 struct font *origfont; 510 511 s = splhigh(); 512 origfont = wsfont_find0(cookie, 0xffffffff); 513 splx(s); 514 515 switch (rotate) { 516 case WSFONT_ROTATE_CW: 517 font = wsfont_rotate_cw_internal(origfont->font); 518 if (font == NULL) 519 return (-1); 520 break; 521 522 case WSFONT_ROTATE_CCW: 523 font = wsfont_rotate_ccw_internal(origfont->font); 524 if (font == NULL) 525 return (-1); 526 break; 527 528 case WSFONT_ROTATE_UD: 529 default: 530 return (-1); 531 } 532 /* rotation works only with bitmap fonts so far */ 533 ncookie = wsfont_find(font->name, font->fontwidth, font->fontheight, 534 font->stride, 0, 0, WSFONT_FIND_BITMAP); 535 536 return (ncookie); 537 } 538 539 #endif /* NRASOPS_ROTATION */ 540 541 void 542 wsfont_init(void) 543 { 544 struct font *ent; 545 static int again; 546 int i; 547 548 if (again != 0) 549 return; 550 again = 1; 551 552 TAILQ_INIT(&list); 553 ent = builtin_fonts; 554 555 for (i = 0; builtin_fonts[i].font != NULL; i++, ent++) { 556 ident += (1 << WSFONT_IDENT_SHIFT); 557 ent->cookie = wsfont_make_cookie(ident, 558 ent->font->bitorder, ent->font->byteorder); 559 TAILQ_INSERT_TAIL(&list, ent, chain); 560 } 561 } 562 563 static struct font * 564 wsfont_find0(int cookie, int mask) 565 { 566 struct font *ent; 567 568 TAILQ_FOREACH(ent, &list, chain) { 569 if ((ent->cookie & mask) == (cookie & mask)) 570 return (ent); 571 } 572 573 return (NULL); 574 } 575 576 int 577 wsfont_matches(struct wsdisplay_font *font, const char *name, 578 int width, int height, int stride, int flags) 579 { 580 int score = 20000; 581 582 /* first weed out fonts the caller doesn't claim support for */ 583 if (FONT_IS_ALPHA(font)) { 584 if (flags & WSFONT_PREFER_ALPHA) 585 score++; 586 if ((flags & WSFONT_FIND_ALPHA) == 0) 587 return 0; 588 } else { 589 if ((flags & WSFONT_FIND_BITMAP) == 0) 590 return 0; 591 } 592 593 if (height != 0 && font->fontheight != height) 594 return (0); 595 596 if (width != 0) { 597 if ((flags & WSFONT_FIND_BESTWIDTH) == 0) { 598 if (font->fontwidth != width) 599 return (0); 600 } else { 601 if (font->fontwidth > width) 602 score -= 10000 + min(font->fontwidth - width, 9999); 603 else 604 score -= min(width - font->fontwidth, 9999); 605 } 606 } 607 608 if (stride != 0 && font->stride != stride) 609 return (0); 610 611 if (name != NULL && strcmp(font->name, name) != 0) 612 return (0); 613 614 return (score); 615 } 616 617 int 618 wsfont_find(const char *name, int width, int height, int stride, int bito, int byteo, int flags) 619 { 620 struct font *ent, *bestent = NULL; 621 int score, bestscore = 0; 622 623 TAILQ_FOREACH(ent, &list, chain) { 624 score = wsfont_matches(ent->font, name, 625 width, height, stride, flags); 626 if (score > bestscore) { 627 bestscore = score; 628 bestent = ent; 629 } 630 } 631 632 if (bestent != NULL) 633 return (wsfont_make_cookie(bestent->cookie, bito, byteo)); 634 635 return (-1); 636 } 637 638 void 639 wsfont_walk(void (*matchfunc)(struct wsdisplay_font *, void *, int), void *cookie) 640 { 641 struct font *ent; 642 643 TAILQ_FOREACH(ent, &list, chain) { 644 matchfunc(ent->font, cookie, ent->cookie); 645 } 646 } 647 648 static struct font * 649 wsfont_add0(struct wsdisplay_font *font, int copy) 650 { 651 struct font *ent; 652 size_t size; 653 654 ent = malloc(sizeof(struct font), M_DEVBUF, M_WAITOK | M_ZERO); 655 656 /* Is this font statically allocated? */ 657 if (!copy) { 658 ent->font = font; 659 ent->flags = WSFONT_STATIC; 660 } else { 661 void *data; 662 char *name; 663 664 ent->font = malloc(sizeof(struct wsdisplay_font), M_DEVBUF, 665 M_WAITOK); 666 memcpy(ent->font, font, sizeof(*ent->font)); 667 668 size = font->fontheight * font->numchars * font->stride; 669 data = malloc(size, M_DEVBUF, M_WAITOK); 670 memcpy(data, font->data, size); 671 ent->font->data = data; 672 673 name = malloc(strlen(font->name) + 1, M_DEVBUF, M_WAITOK); 674 strlcpy(name, font->name, strlen(font->name) + 1); 675 ent->font->name = name; 676 } 677 678 TAILQ_INSERT_TAIL(&list, ent, chain); 679 return (ent); 680 } 681 682 int 683 wsfont_add(struct wsdisplay_font *font, int copy) 684 { 685 struct font *ent; 686 687 /* Don't allow exact duplicates */ 688 if (wsfont_find(font->name, font->fontwidth, font->fontheight, 689 font->stride, 0, 0, WSFONT_FIND_ALL) >= 0) 690 return (EEXIST); 691 692 ent = wsfont_add0(font, copy); 693 694 ident += (1 << WSFONT_IDENT_SHIFT); 695 ent->cookie = wsfont_make_cookie(ident, font->bitorder, 696 font->byteorder); 697 698 return (0); 699 } 700 701 int 702 wsfont_remove(int cookie) 703 { 704 struct font *ent; 705 706 if ((ent = wsfont_find0(cookie, 0xffffffff)) == NULL) 707 return (ENOENT); 708 709 if ((ent->flags & WSFONT_BUILTIN) != 0 || ent->lockcount != 0) 710 return (EBUSY); 711 712 if ((ent->flags & WSFONT_STATIC) == 0) { 713 free(ent->font->data, M_DEVBUF); 714 free(__UNCONST(ent->font->name), M_DEVBUF); /*XXXUNCONST*/ 715 free(ent->font, M_DEVBUF); 716 } 717 718 TAILQ_REMOVE(&list, ent, chain); 719 free(ent, M_DEVBUF); 720 721 return (0); 722 } 723 724 int 725 wsfont_lock(int cookie, struct wsdisplay_font **ptr) 726 { 727 struct font *ent, *neu; 728 int bito, byteo; 729 730 if ((ent = wsfont_find0(cookie, 0xffffffff)) == NULL) { 731 if ((ent = wsfont_find0(cookie, WSFONT_IDENT_MASK)) == NULL) 732 return (ENOENT); 733 734 bito = (cookie & WSFONT_BITO_MASK) >> WSFONT_BITO_SHIFT; 735 byteo = (cookie & WSFONT_BYTEO_MASK) >> WSFONT_BYTEO_SHIFT; 736 737 if (ent->lockcount != 0) { 738 neu = wsfont_add0(ent->font, 1); 739 neu->flags |= WSFONT_COPY; 740 741 aprint_debug("wsfont: font '%s' bito %d byteo %d " 742 "copied to bito %d byteo %d\n", 743 ent->font->name, 744 ent->font->bitorder, ent->font->byteorder, 745 bito, byteo); 746 747 ent = neu; 748 } 749 750 if (bito && bito != ent->font->bitorder) { 751 wsfont_revbit(ent->font); 752 ent->font->bitorder = bito; 753 } 754 755 if (byteo && byteo != ent->font->byteorder) { 756 wsfont_revbyte(ent->font); 757 ent->font->byteorder = byteo; 758 } 759 760 ent->cookie = cookie; 761 } 762 763 ent->lockcount++; 764 *ptr = ent->font; 765 return (0); 766 } 767 768 int 769 wsfont_unlock(int cookie) 770 { 771 struct font *ent; 772 773 if ((ent = wsfont_find0(cookie, 0xffffffff)) == NULL) 774 return (ENOENT); 775 776 if (ent->lockcount == 0) 777 panic("wsfont_unlock: font not locked"); 778 779 if (--ent->lockcount == 0 && (ent->flags & WSFONT_COPY) != 0) 780 wsfont_remove(cookie); 781 782 return (0); 783 } 784 785 /* 786 * Unicode to font encoding mappings 787 */ 788 789 /* 790 * To save memory, font encoding tables use a two level lookup. First the 791 * high byte of the Unicode is used to lookup the level 2 table, then the 792 * low byte indexes that table. Level 2 tables that are not needed are 793 * omitted (NULL), and both level 1 and level 2 tables have base and size 794 * attributes to keep their size down. 795 */ 796 797 struct wsfont_level1_glyphmap { 798 const struct wsfont_level2_glyphmap **level2; 799 int base; /* High byte for first level2 entry */ 800 int size; /* Number of level2 entries */ 801 }; 802 803 struct wsfont_level2_glyphmap { 804 int base; /* Low byte for first character */ 805 int size; /* Number of characters */ 806 const void *chars; /* Pointer to character number entries */ 807 int width; /* Size of each entry in bytes (1,2,4) */ 808 }; 809 810 #define null16 \ 811 NULL, NULL, NULL, NULL, \ 812 NULL, NULL, NULL, NULL, \ 813 NULL, NULL, NULL, NULL, \ 814 NULL, NULL, NULL, NULL 815 816 /* 817 * IBM 437 maps 818 */ 819 820 static const u_int8_t ibm437_chars_0[] = { 821 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 822 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 823 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 824 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 825 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 826 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 827 96, 97, 98, 99, 100,101,102,103,104,105,106,107,108,109,110,111, 828 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, 829 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 830 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 831 255,173,155,156, 0, 157, 0, 0, 0, 0, 166,174,170, 0, 0, 0, 832 0, 241,253, 0, 0, 0, 0, 249, 0, 0, 167,175,172,171, 0, 168, 833 0, 0, 0, 0, 142,143,146,128, 0, 144, 0, 0, 0, 0, 0, 0, 834 0, 165, 0, 0, 0, 0, 153, 0, 0, 0, 0, 0, 154, 0, 0, 0, 835 133,160,131, 0, 132,134,145,135,138,130,136,137,141,161,140,139, 836 0, 164,149,162,147, 0, 148,246, 0, 151,163,150,129, 0, 0, 152 837 }; 838 839 static const u_int8_t ibm437_chars_1[] = { 840 159 841 }; 842 843 static const u_int8_t ibm437_chars_3[] = { 844 226, 0, 0, 0, 0, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 845 228, 0, 0, 232, 0, 0, 234, 0, 0, 0, 0, 0, 0, 0, 224,225, 846 0, 235,238, 0, 0, 0, 0, 0, 0, 230, 0, 0, 0, 227, 0, 0, 847 229,231 848 }; 849 850 static const u_int8_t ibm437_chars_32[] = { 851 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 852 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 853 0, 0, 0, 0, 0, 0, 0, 0, 158 854 }; 855 856 static const u_int8_t ibm437_chars_34[] = { 857 237, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 858 0, 0, 0, 248,250,251, 0, 0, 0, 236, 0, 0, 0, 0, 0, 0, 859 0, 0, 0, 0, 239, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 860 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 861 0, 0, 0, 247, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 862 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 0, 0,243, 863 242 864 }; 865 866 static const u_int8_t ibm437_chars_35[] = { 867 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 868 244,245 869 }; 870 871 static const u_int8_t ibm437_chars_37[] = { 872 196,205,179,186, 0, 0, 0, 0, 0, 0, 0, 0, 218,213,214,201, 873 191,184,183,187,192,212,211,200,217,190,189,188,195,198, 0, 0, 874 199, 0, 0, 204,180,181, 0, 0, 182, 0, 0, 185,194, 0, 0, 209, 875 210, 0, 0, 203,193, 0, 0, 207,208, 0, 0, 202,197, 0, 0, 216, 876 0, 0, 215, 0, 0, 0, 0, 0, 0, 0, 0, 206, 0, 0, 0, 0, 877 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 878 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 879 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 880 223, 0, 0, 0, 220, 0, 0, 0, 219, 0, 0, 0, 221, 0, 0, 0, 881 222,176,177,178, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 882 254 883 }; 884 885 static const struct wsfont_level2_glyphmap ibm437_level2_0 = 886 { 0, 256, ibm437_chars_0, 1 }; 887 888 static const struct wsfont_level2_glyphmap ibm437_level2_1 = 889 { 146, 1, ibm437_chars_1, 1 }; 890 891 static const struct wsfont_level2_glyphmap ibm437_level2_3 = 892 { 147, 50, ibm437_chars_3, 1 }; 893 894 static const struct wsfont_level2_glyphmap ibm437_level2_32 = 895 { 127, 41, ibm437_chars_32, 1 }; 896 897 static const struct wsfont_level2_glyphmap ibm437_level2_34 = 898 { 5, 97, ibm437_chars_34, 1 }; 899 900 static const struct wsfont_level2_glyphmap ibm437_level2_35 = 901 { 16, 18, ibm437_chars_35, 1 }; 902 903 static const struct wsfont_level2_glyphmap ibm437_level2_37 = 904 { 0, 161, ibm437_chars_37, 1 }; 905 906 static const struct wsfont_level2_glyphmap *ibm437_level1[] = { 907 &ibm437_level2_0, &ibm437_level2_1, NULL, &ibm437_level2_3, 908 NULL, NULL, NULL, NULL, 909 NULL, NULL, NULL, NULL, 910 NULL, NULL, NULL, NULL, 911 NULL, NULL, NULL, NULL, 912 NULL, NULL, NULL, NULL, 913 NULL, NULL, NULL, NULL, 914 NULL, NULL, NULL, NULL, 915 &ibm437_level2_32, NULL, &ibm437_level2_34, &ibm437_level2_35, 916 NULL, &ibm437_level2_37 917 }; 918 919 /* 920 * ISO-8859-7 maps 921 */ 922 static const u_int8_t iso7_chars_0[] = { 923 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 924 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 925 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 926 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 927 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 928 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 929 96, 97, 98, 99, 100,101,102,103,104,105,106,107,108,109,110,111, 930 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, 931 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, 932 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, 933 160, 0, 0, 163, 0, 0, 166,167,168,169, 0, 171,172,173, 0, 0, 934 176,177,178,179,180, 0, 0, 183, 0, 0, 0, 187, 0, 189 935 }; 936 937 static const u_int8_t iso7_chars_3[] = { 938 182, 0, 184,185,186, 0, 188, 0, 190,191,192,193,194,195,196,197, 939 198,199,200,201,202,203,204,205,206,207,208,209, 0, 211,212,213, 940 214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229, 941 230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245, 942 246,247,248,249,250,251,252,253,254, 0, 0, 0, 0, 0, 0, 0, 943 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 944 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181 945 }; 946 947 /* 948 * map all variants of the box drawing characters to the same basic shapes for 949 * now, encoded like this: 950 * 951 * 1 952 * 1 953 * 888 222 954 * 4 955 * 4 956 * 957 * so an upright line would be 0x05 958 */ 959 #define FL |WSFONT_FLAG_OPT 960 static const u_int32_t netbsd_boxes[] = { 961 /*00*/ 0x0a FL, 0x0a FL, 0x05 FL, 0x05 FL, 0x0a FL, 0x0a FL, 0x05 FL, 0x05 FL, 962 /*08*/ 0x0a FL, 0x0a FL, 0x05 FL, 0x05 FL, 0x06 FL, 0x06 FL, 0x06 FL, 0x06 FL, 963 /*10*/ 0x0c FL, 0x0c FL, 0x0c FL, 0x0c FL, 0x03 FL, 0x03 FL, 0x03 FL, 0x03 FL, 964 /*18*/ 0x09 FL, 0x09 FL, 0x09 FL, 0x09 FL, 0x07 FL, 0x07 FL, 0x07 FL, 0x07 FL, 965 /*20*/ 0x07 FL, 0x07 FL, 0x07 FL, 0x07 FL, 0x0d FL, 0x0d FL, 0x0d FL, 0x0d FL, 966 /*28*/ 0x0d FL, 0x0d FL, 0x0d FL, 0x0d FL, 0x0e FL, 0x0e FL, 0x0e FL, 0x0e FL, 967 /*30*/ 0x0e FL, 0x0e FL, 0x0e FL, 0x0e FL, 0x0b FL, 0x0b FL, 0x0b FL, 0x0b FL, 968 /*38*/ 0x0b FL, 0x0b FL, 0x0b FL, 0x0b FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 969 /*40*/ 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 970 /*48*/ 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0a FL, 0x0a FL, 0x05 FL, 0x05 FL, 971 /*50*/ 0x0a FL, 0x05 FL, 0x06 FL, 0x06 FL, 0x06 FL, 0x0c FL, 0x0c FL, 0x0c FL, 972 /*58*/ 0x03 FL, 0x03 FL, 0x03 FL, 0x09 FL, 0x09 FL, 0x09 FL, 0x07 FL, 0x07 FL, 973 /*60*/ 0x07 FL, 0x0d FL, 0x0d FL, 0x0d FL, 0x0e FL, 0x0e FL, 0x0e FL, 0x0b FL, 974 /*68*/ 0x0b FL, 0x0b FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x06 FL, 0x0c FL, 0x09 FL, 975 /*70*/ 0x03 FL, 0 FL, 0 FL, 0 FL, 0x08 FL, 0x01 FL, 0x02 FL, 0x04 FL, 976 /*78*/ 0x08 FL, 0x01 FL, 0x02 FL, 0x04 FL, 0x0a FL, 0x05 FL, 0x0a FL, 0x05 FL 977 }; 978 #undef FL 979 980 static const u_int8_t iso7_chars_32[] = { 981 175, 0, 0, 0, 0, 162, 0, 161 982 }; 983 984 static const struct wsfont_level2_glyphmap iso7_level2_0 = 985 { 0, 190, iso7_chars_0, 1 }; 986 987 static const struct wsfont_level2_glyphmap iso7_level2_3 = 988 { 134, 111, iso7_chars_3, 1 }; 989 990 static const struct wsfont_level2_glyphmap iso7_level2_32 = 991 { 20, 8, iso7_chars_32, 1 }; 992 993 static const struct wsfont_level2_glyphmap netbsd_box_drawing = 994 { 0, 128, netbsd_boxes, 4 }; 995 996 static const struct wsfont_level2_glyphmap *iso7_level1[] = { 997 &iso7_level2_0, NULL, NULL, &iso7_level2_3, 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 &iso7_level2_32, NULL, NULL, NULL, 1006 NULL, &netbsd_box_drawing 1007 }; 1008 1009 static const struct wsfont_level2_glyphmap *iso_level1[] = { 1010 NULL, NULL, NULL, NULL, 1011 NULL, NULL, NULL, NULL, 1012 NULL, NULL, NULL, NULL, 1013 NULL, NULL, NULL, NULL, 1014 NULL, NULL, NULL, NULL, 1015 NULL, NULL, NULL, NULL, 1016 NULL, NULL, NULL, NULL, 1017 NULL, NULL, NULL, NULL, 1018 NULL, NULL, NULL, NULL, 1019 NULL, &netbsd_box_drawing 1020 }; 1021 1022 static const struct wsfont_level1_glyphmap encodings[] = { 1023 { iso_level1, 0, 0x26 }, /* WSDISPLAY_FONTENC_ISO */ 1024 { ibm437_level1, 0, 38 }, /* WSDISPLAY_FONTENC_IBM */ 1025 { NULL, 0, 0 }, /* WSDISPLAY_FONTENC_PCVT */ 1026 { iso7_level1, 0, 0x26 }, /* WSDISPLAY_FONTENC_ISO7 */ 1027 }; 1028 1029 #define MAX_ENCODING (sizeof(encodings) / sizeof(encodings[0])) 1030 1031 /* 1032 * Remap Unicode character to glyph 1033 */ 1034 int 1035 wsfont_map_unichar(struct wsdisplay_font *font, int c) 1036 { 1037 const struct wsfont_level1_glyphmap *map1; 1038 const struct wsfont_level2_glyphmap *map2; 1039 int hi, lo; 1040 1041 if (font->encoding < 0 || font->encoding >= MAX_ENCODING) 1042 return (-1); 1043 1044 hi = (c >> 8); 1045 lo = c & 255; 1046 map1 = &encodings[font->encoding]; 1047 1048 if (hi < map1->base || hi >= map1->base + map1->size) 1049 return (-1); 1050 1051 map2 = map1->level2[hi - map1->base]; 1052 1053 /* so we don't need an identical level 2 table for hi == 0 */ 1054 if (hi == 0 && font->encoding == WSDISPLAY_FONTENC_ISO) 1055 return lo; 1056 1057 if (map2 == NULL || lo < map2->base || lo >= map2->base + map2->size) 1058 return (-1); 1059 1060 lo -= map2->base; 1061 1062 switch(map2->width) { 1063 case 1: 1064 c = (((const u_int8_t *)map2->chars)[lo]); 1065 break; 1066 case 2: 1067 c = (((const u_int16_t *)map2->chars)[lo]); 1068 break; 1069 case 4: 1070 c = (((const u_int32_t *)map2->chars)[lo]); 1071 break; 1072 } 1073 1074 if (c == 0 && lo != 0) 1075 return (-1); 1076 1077 return (c); 1078 } 1079