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