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