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