1 /* $NetBSD: wsfont.c,v 1.57 2015/01/25 20:09:42 christos 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.57 2015/01/25 20:09:42 christos 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 574 /* first weed out fonts the caller doesn't claim support for */ 575 if (FONT_IS_ALPHA(font)) { 576 if ((flags & WSFONT_FIND_ALPHA) == 0) 577 return 0; 578 } else { 579 if ((flags & WSFONT_FIND_BITMAP) == 0) 580 return 0; 581 } 582 583 if (height != 0 && font->fontheight != height) 584 return (0); 585 586 if (width != 0 && font->fontwidth != width) 587 return (0); 588 589 if (stride != 0 && font->stride != stride) 590 return (0); 591 592 if (name != NULL && strcmp(font->name, name) != 0) 593 return (0); 594 595 return (1); 596 } 597 598 int 599 wsfont_find(const char *name, int width, int height, int stride, int bito, int byteo, int flags) 600 { 601 struct font *ent; 602 603 TAILQ_FOREACH(ent, &list, chain) { 604 if (wsfont_matches(ent->font, name, width, height, stride, flags)) 605 return (wsfont_make_cookie(ent->cookie, bito, byteo)); 606 } 607 608 return (-1); 609 } 610 611 void 612 wsfont_walk(void (*matchfunc)(struct wsdisplay_font *, void *, int), void *cookie) 613 { 614 struct font *ent; 615 616 TAILQ_FOREACH(ent, &list, chain) { 617 matchfunc(ent->font, cookie, ent->cookie); 618 } 619 } 620 621 static struct font * 622 wsfont_add0(struct wsdisplay_font *font, int copy) 623 { 624 struct font *ent; 625 size_t size; 626 627 ent = malloc(sizeof(struct font), M_DEVBUF, M_WAITOK | M_ZERO); 628 629 /* Is this font statically allocated? */ 630 if (!copy) { 631 ent->font = font; 632 ent->flags = WSFONT_STATIC; 633 } else { 634 void *data; 635 char *name; 636 637 ent->font = malloc(sizeof(struct wsdisplay_font), M_DEVBUF, 638 M_WAITOK); 639 memcpy(ent->font, font, sizeof(*ent->font)); 640 641 size = font->fontheight * font->numchars * font->stride; 642 data = malloc(size, M_DEVBUF, M_WAITOK); 643 memcpy(data, font->data, size); 644 ent->font->data = data; 645 646 name = malloc(strlen(font->name) + 1, M_DEVBUF, M_WAITOK); 647 strlcpy(name, font->name, strlen(font->name) + 1); 648 ent->font->name = name; 649 } 650 651 TAILQ_INSERT_TAIL(&list, ent, chain); 652 return (ent); 653 } 654 655 int 656 wsfont_add(struct wsdisplay_font *font, int copy) 657 { 658 struct font *ent; 659 660 /* Don't allow exact duplicates */ 661 if (wsfont_find(font->name, font->fontwidth, font->fontheight, 662 font->stride, 0, 0, WSFONT_FIND_ALL) >= 0) 663 return (EEXIST); 664 665 ent = wsfont_add0(font, copy); 666 667 ident += (1 << WSFONT_IDENT_SHIFT); 668 ent->cookie = wsfont_make_cookie(ident, font->bitorder, 669 font->byteorder); 670 671 return (0); 672 } 673 674 int 675 wsfont_remove(int cookie) 676 { 677 struct font *ent; 678 679 if ((ent = wsfont_find0(cookie, 0xffffffff)) == NULL) 680 return (ENOENT); 681 682 if ((ent->flags & WSFONT_BUILTIN) != 0 || ent->lockcount != 0) 683 return (EBUSY); 684 685 if ((ent->flags & WSFONT_STATIC) == 0) { 686 free(ent->font->data, M_DEVBUF); 687 free(__UNCONST(ent->font->name), M_DEVBUF); /*XXXUNCONST*/ 688 free(ent->font, M_DEVBUF); 689 } 690 691 TAILQ_REMOVE(&list, ent, chain); 692 free(ent, M_DEVBUF); 693 694 return (0); 695 } 696 697 int 698 wsfont_lock(int cookie, struct wsdisplay_font **ptr) 699 { 700 struct font *ent, *neu; 701 int bito, byteo; 702 703 if ((ent = wsfont_find0(cookie, 0xffffffff)) == NULL) { 704 if ((ent = wsfont_find0(cookie, WSFONT_IDENT_MASK)) == NULL) 705 return (ENOENT); 706 707 bito = (cookie & WSFONT_BITO_MASK) >> WSFONT_BITO_SHIFT; 708 byteo = (cookie & WSFONT_BYTEO_MASK) >> WSFONT_BYTEO_SHIFT; 709 710 if (ent->lockcount != 0) { 711 neu = wsfont_add0(ent->font, 1); 712 neu->flags |= WSFONT_COPY; 713 714 aprint_debug("wsfont: font '%s' bito %d byteo %d " 715 "copied to bito %d byteo %d\n", 716 ent->font->name, 717 ent->font->bitorder, ent->font->byteorder, 718 bito, byteo); 719 720 ent = neu; 721 } 722 723 if (bito && bito != ent->font->bitorder) { 724 wsfont_revbit(ent->font); 725 ent->font->bitorder = bito; 726 } 727 728 if (byteo && byteo != ent->font->byteorder) { 729 wsfont_revbyte(ent->font); 730 ent->font->byteorder = byteo; 731 } 732 733 ent->cookie = cookie; 734 } 735 736 ent->lockcount++; 737 *ptr = ent->font; 738 return (0); 739 } 740 741 int 742 wsfont_unlock(int cookie) 743 { 744 struct font *ent; 745 746 if ((ent = wsfont_find0(cookie, 0xffffffff)) == NULL) 747 return (ENOENT); 748 749 if (ent->lockcount == 0) 750 panic("wsfont_unlock: font not locked"); 751 752 if (--ent->lockcount == 0 && (ent->flags & WSFONT_COPY) != 0) 753 wsfont_remove(cookie); 754 755 return (0); 756 } 757 758 /* 759 * Unicode to font encoding mappings 760 */ 761 762 /* 763 * To save memory, font encoding tables use a two level lookup. First the 764 * high byte of the Unicode is used to lookup the level 2 table, then the 765 * low byte indexes that table. Level 2 tables that are not needed are 766 * omitted (NULL), and both level 1 and level 2 tables have base and size 767 * attributes to keep their size down. 768 */ 769 770 struct wsfont_level1_glyphmap { 771 const struct wsfont_level2_glyphmap **level2; 772 int base; /* High byte for first level2 entry */ 773 int size; /* Number of level2 entries */ 774 }; 775 776 struct wsfont_level2_glyphmap { 777 int base; /* Low byte for first character */ 778 int size; /* Number of characters */ 779 const void *chars; /* Pointer to character number entries */ 780 int width; /* Size of each entry in bytes (1,2,4) */ 781 }; 782 783 #define null16 \ 784 NULL, NULL, NULL, NULL, \ 785 NULL, NULL, NULL, NULL, \ 786 NULL, NULL, NULL, NULL, \ 787 NULL, NULL, NULL, NULL 788 789 /* 790 * IBM 437 maps 791 */ 792 793 static const u_int8_t ibm437_chars_0[] = { 794 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 795 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 796 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 797 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 798 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 799 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 800 96, 97, 98, 99, 100,101,102,103,104,105,106,107,108,109,110,111, 801 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, 802 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 803 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 804 255,173,155,156, 0, 157, 0, 0, 0, 0, 166,174,170, 0, 0, 0, 805 0, 241,253, 0, 0, 0, 0, 249, 0, 0, 167,175,172,171, 0, 168, 806 0, 0, 0, 0, 142,143,146,128, 0, 144, 0, 0, 0, 0, 0, 0, 807 0, 165, 0, 0, 0, 0, 153, 0, 0, 0, 0, 0, 154, 0, 0, 0, 808 133,160,131, 0, 132,134,145,135,138,130,136,137,141,161,140,139, 809 0, 164,149,162,147, 0, 148,246, 0, 151,163,150,129, 0, 0, 152 810 }; 811 812 static const u_int8_t ibm437_chars_1[] = { 813 159 814 }; 815 816 static const u_int8_t ibm437_chars_3[] = { 817 226, 0, 0, 0, 0, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 818 228, 0, 0, 232, 0, 0, 234, 0, 0, 0, 0, 0, 0, 0, 224,225, 819 0, 235,238, 0, 0, 0, 0, 0, 0, 230, 0, 0, 0, 227, 0, 0, 820 229,231 821 }; 822 823 static const u_int8_t ibm437_chars_32[] = { 824 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 825 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 826 0, 0, 0, 0, 0, 0, 0, 0, 158 827 }; 828 829 static const u_int8_t ibm437_chars_34[] = { 830 237, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 831 0, 0, 0, 248,250,251, 0, 0, 0, 236, 0, 0, 0, 0, 0, 0, 832 0, 0, 0, 0, 239, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 833 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 834 0, 0, 0, 247, 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,240, 0, 0,243, 836 242 837 }; 838 839 static const u_int8_t ibm437_chars_35[] = { 840 169, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 841 244,245 842 }; 843 844 static const u_int8_t ibm437_chars_37[] = { 845 196,205,179,186, 0, 0, 0, 0, 0, 0, 0, 0, 218,213,214,201, 846 191,184,183,187,192,212,211,200,217,190,189,188,195,198, 0, 0, 847 199, 0, 0, 204,180,181, 0, 0, 182, 0, 0, 185,194, 0, 0, 209, 848 210, 0, 0, 203,193, 0, 0, 207,208, 0, 0, 202,197, 0, 0, 216, 849 0, 0, 215, 0, 0, 0, 0, 0, 0, 0, 0, 206, 0, 0, 0, 0, 850 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 853 223, 0, 0, 0, 220, 0, 0, 0, 219, 0, 0, 0, 221, 0, 0, 0, 854 222,176,177,178, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 855 254 856 }; 857 858 static const struct wsfont_level2_glyphmap ibm437_level2_0 = 859 { 0, 256, ibm437_chars_0, 1 }; 860 861 static const struct wsfont_level2_glyphmap ibm437_level2_1 = 862 { 146, 1, ibm437_chars_1, 1 }; 863 864 static const struct wsfont_level2_glyphmap ibm437_level2_3 = 865 { 147, 50, ibm437_chars_3, 1 }; 866 867 static const struct wsfont_level2_glyphmap ibm437_level2_32 = 868 { 127, 41, ibm437_chars_32, 1 }; 869 870 static const struct wsfont_level2_glyphmap ibm437_level2_34 = 871 { 5, 97, ibm437_chars_34, 1 }; 872 873 static const struct wsfont_level2_glyphmap ibm437_level2_35 = 874 { 16, 18, ibm437_chars_35, 1 }; 875 876 static const struct wsfont_level2_glyphmap ibm437_level2_37 = 877 { 0, 161, ibm437_chars_37, 1 }; 878 879 static const struct wsfont_level2_glyphmap *ibm437_level1[] = { 880 &ibm437_level2_0, &ibm437_level2_1, NULL, &ibm437_level2_3, 881 NULL, NULL, NULL, NULL, 882 NULL, NULL, NULL, NULL, 883 NULL, NULL, NULL, NULL, 884 NULL, NULL, NULL, NULL, 885 NULL, NULL, NULL, NULL, 886 NULL, NULL, NULL, NULL, 887 NULL, NULL, NULL, NULL, 888 &ibm437_level2_32, NULL, &ibm437_level2_34, &ibm437_level2_35, 889 NULL, &ibm437_level2_37 890 }; 891 892 /* 893 * ISO-8859-7 maps 894 */ 895 static const u_int8_t iso7_chars_0[] = { 896 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 897 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 898 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 899 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 900 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 901 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 902 96, 97, 98, 99, 100,101,102,103,104,105,106,107,108,109,110,111, 903 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, 904 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, 905 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, 906 160, 0, 0, 163, 0, 0, 166,167,168,169, 0, 171,172,173, 0, 0, 907 176,177,178,179,180, 0, 0, 183, 0, 0, 0, 187, 0, 189 908 }; 909 910 static const u_int8_t iso7_chars_3[] = { 911 182, 0, 184,185,186, 0, 188, 0, 190,191,192,193,194,195,196,197, 912 198,199,200,201,202,203,204,205,206,207,208,209, 0, 211,212,213, 913 214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229, 914 230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245, 915 246,247,248,249,250,251,252,253,254, 0, 0, 0, 0, 0, 0, 0, 916 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 917 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 181 918 }; 919 920 /* 921 * map all variants of the box drawing characters to the same basic shapes for 922 * now, encoded like this: 923 * 924 * 1 925 * 1 926 * 888 222 927 * 4 928 * 4 929 * 930 * so an upright line would be 0x05 931 */ 932 #define FL |WSFONT_FLAG_OPT 933 static const u_int32_t netbsd_boxes[] = { 934 /*00*/ 0x0a FL, 0x0a FL, 0x05 FL, 0x05 FL, 0x0a FL, 0x0a FL, 0x05 FL, 0x05 FL, 935 /*08*/ 0x0a FL, 0x0a FL, 0x05 FL, 0x05 FL, 0x06 FL, 0x06 FL, 0x06 FL, 0x06 FL, 936 /*10*/ 0x0c FL, 0x0c FL, 0x0c FL, 0x0c FL, 0x03 FL, 0x03 FL, 0x03 FL, 0x03 FL, 937 /*18*/ 0x09 FL, 0x09 FL, 0x09 FL, 0x09 FL, 0x07 FL, 0x07 FL, 0x07 FL, 0x07 FL, 938 /*20*/ 0x07 FL, 0x07 FL, 0x07 FL, 0x07 FL, 0x0d FL, 0x0d FL, 0x0d FL, 0x0d FL, 939 /*28*/ 0x0d FL, 0x0d FL, 0x0d FL, 0x0d FL, 0x0e FL, 0x0e FL, 0x0e FL, 0x0e FL, 940 /*30*/ 0x0e FL, 0x0e FL, 0x0e FL, 0x0e FL, 0x0b FL, 0x0b FL, 0x0b FL, 0x0b FL, 941 /*38*/ 0x0b FL, 0x0b FL, 0x0b FL, 0x0b FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 942 /*40*/ 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 943 /*48*/ 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0a FL, 0x0a FL, 0x05 FL, 0x05 FL, 944 /*50*/ 0x0a FL, 0x05 FL, 0x06 FL, 0x06 FL, 0x06 FL, 0x0c FL, 0x0c FL, 0x0c FL, 945 /*58*/ 0x03 FL, 0x03 FL, 0x03 FL, 0x09 FL, 0x09 FL, 0x09 FL, 0x07 FL, 0x07 FL, 946 /*60*/ 0x07 FL, 0x0d FL, 0x0d FL, 0x0d FL, 0x0e FL, 0x0e FL, 0x0e FL, 0x0b FL, 947 /*68*/ 0x0b FL, 0x0b FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x06 FL, 0x0c FL, 0x09 FL, 948 /*70*/ 0x03 FL, 0 FL, 0 FL, 0 FL, 0x08 FL, 0x01 FL, 0x02 FL, 0x04 FL, 949 /*78*/ 0x08 FL, 0x01 FL, 0x02 FL, 0x04 FL, 0x0a FL, 0x05 FL, 0x0a FL, 0x05 FL 950 }; 951 #undef FL 952 953 static const u_int8_t iso7_chars_32[] = { 954 175, 0, 0, 0, 0, 162, 0, 161 955 }; 956 957 static const struct wsfont_level2_glyphmap iso7_level2_0 = 958 { 0, 190, iso7_chars_0, 1 }; 959 960 static const struct wsfont_level2_glyphmap iso7_level2_3 = 961 { 134, 111, iso7_chars_3, 1 }; 962 963 static const struct wsfont_level2_glyphmap iso7_level2_32 = 964 { 20, 8, iso7_chars_32, 1 }; 965 966 static const struct wsfont_level2_glyphmap netbsd_box_drawing = 967 { 0, 128, netbsd_boxes, 4 }; 968 969 static const struct wsfont_level2_glyphmap *iso7_level1[] = { 970 &iso7_level2_0, NULL, NULL, &iso7_level2_3, 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, NULL, NULL, NULL, 977 NULL, NULL, NULL, NULL, 978 &iso7_level2_32, NULL, NULL, NULL, 979 NULL, &netbsd_box_drawing 980 }; 981 982 static const struct wsfont_level2_glyphmap *iso_level1[] = { 983 NULL, NULL, NULL, NULL, 984 NULL, NULL, NULL, NULL, 985 NULL, NULL, NULL, NULL, 986 NULL, NULL, NULL, NULL, 987 NULL, NULL, NULL, NULL, 988 NULL, NULL, NULL, NULL, 989 NULL, NULL, NULL, NULL, 990 NULL, NULL, NULL, NULL, 991 NULL, NULL, NULL, NULL, 992 NULL, &netbsd_box_drawing 993 }; 994 995 static const struct wsfont_level1_glyphmap encodings[] = { 996 { iso_level1, 0, 0x26 }, /* WSDISPLAY_FONTENC_ISO */ 997 { ibm437_level1, 0, 38 }, /* WSDISPLAY_FONTENC_IBM */ 998 { NULL, 0, 0 }, /* WSDISPLAY_FONTENC_PCVT */ 999 { iso7_level1, 0, 0x26 }, /* WSDISPLAY_FONTENC_ISO7 */ 1000 }; 1001 1002 #define MAX_ENCODING (sizeof(encodings) / sizeof(encodings[0])) 1003 1004 /* 1005 * Remap Unicode character to glyph 1006 */ 1007 int 1008 wsfont_map_unichar(struct wsdisplay_font *font, int c) 1009 { 1010 const struct wsfont_level1_glyphmap *map1; 1011 const struct wsfont_level2_glyphmap *map2; 1012 int hi, lo; 1013 1014 if (font->encoding < 0 || font->encoding >= MAX_ENCODING) 1015 return (-1); 1016 1017 hi = (c >> 8); 1018 lo = c & 255; 1019 map1 = &encodings[font->encoding]; 1020 1021 if (hi < map1->base || hi >= map1->base + map1->size) 1022 return (-1); 1023 1024 map2 = map1->level2[hi - map1->base]; 1025 1026 /* so we don't need an identical level 2 table for hi == 0 */ 1027 if (hi == 0 && font->encoding == WSDISPLAY_FONTENC_ISO) 1028 return lo; 1029 1030 if (map2 == NULL || lo < map2->base || lo >= map2->base + map2->size) 1031 return (-1); 1032 1033 lo -= map2->base; 1034 1035 switch(map2->width) { 1036 case 1: 1037 c = (((const u_int8_t *)map2->chars)[lo]); 1038 break; 1039 case 2: 1040 c = (((const u_int16_t *)map2->chars)[lo]); 1041 break; 1042 case 4: 1043 c = (((const u_int32_t *)map2->chars)[lo]); 1044 break; 1045 } 1046 1047 if (c == 0 && lo != 0) 1048 return (-1); 1049 1050 return (c); 1051 } 1052