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