1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Copyright 2017 Toomas Soome <tsoome@me.com> 29 */ 30 31 /* 32 * Generic font related data and functions shared by early boot console 33 * in dboot, kernel startup and full kernel. 34 */ 35 #include <sys/types.h> 36 #include <sys/systm.h> 37 #include <sys/tem_impl.h> 38 #include <sys/rgb.h> 39 #include <sys/font.h> 40 #include <sys/sysmacros.h> 41 42 /* 43 * To simplify my life, I am "temporarily" collecting the commonly used 44 * color bits here. The bits shared between loader, dboot, early boot, tem. 45 * This data would need some sort of API, but I am in no condition to figure 46 * something out right now. 47 */ 48 49 /* ANSI color to sun color translation. */ 50 /* BEGIN CSTYLED */ 51 /* Bk Rd Gr Br Bl Mg Cy Wh */ 52 const uint8_t dim_xlate[] = { 1, 5, 3, 7, 2, 6, 4, 8 }; 53 const uint8_t brt_xlate[] = { 9, 13, 11, 15, 10, 14, 12, 0 }; 54 55 const uint8_t solaris_color_to_pc_color[16] = { 56 pc_brt_white, /* 0 - brt_white */ 57 pc_black, /* 1 - black */ 58 pc_blue, /* 2 - blue */ 59 pc_green, /* 3 - green */ 60 pc_cyan, /* 4 - cyan */ 61 pc_red, /* 5 - red */ 62 pc_magenta, /* 6 - magenta */ 63 pc_brown, /* 7 - brown */ 64 pc_white, /* 8 - white */ 65 pc_grey, /* 9 - gery */ 66 pc_brt_blue, /* 10 - brt_blue */ 67 pc_brt_green, /* 11 - brt_green */ 68 pc_brt_cyan, /* 12 - brt_cyan */ 69 pc_brt_red, /* 13 - brt_red */ 70 pc_brt_magenta, /* 14 - brt_magenta */ 71 pc_yellow /* 15 - yellow */ 72 }; 73 74 /* 4-bit to 24-bit color translation. */ 75 const text_cmap_t cmap4_to_24 = { 76 /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 77 Wh+ Bk Bl Gr Cy Rd Mg Br Wh Bk+ Bl+ Gr+ Cy+ Rd+ Mg+ Yw */ 78 .red = { 79 0xff,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x40,0x00,0x00,0x00,0xff,0xff,0xff 80 }, 81 .green = { 82 0xff,0x00,0x00,0x80,0x80,0x00,0x00,0x80,0x80,0x40,0x00,0xff,0xff,0x00,0x00,0xff 83 }, 84 .blue = { 85 0xff,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x40,0xff,0x00,0xff,0x00,0xff,0x00 86 } 87 }; 88 /* END CSTYLED */ 89 90 /* 91 * Fonts are statically linked with this module. At some point an 92 * RFE might be desireable to allow dynamic font loading. The 93 * original intention to facilitate dynamic fonts can be seen 94 * by examining the data structures and set_font(). As much of 95 * the original code is retained but modified to be suited for 96 * traversing a list of static fonts. 97 */ 98 99 /* 100 * Must be sorted by font size in descending order 101 */ 102 font_list_t fonts = STAILQ_HEAD_INITIALIZER(fonts); 103 104 bitmap_data_t * 105 set_font(short *rows, short *cols, short h, short w) 106 { 107 bitmap_data_t *font = NULL; 108 struct fontlist *fl; 109 unsigned height = h; 110 unsigned width = w; 111 112 /* 113 * First check for manually loaded font. 114 */ 115 STAILQ_FOREACH(fl, &fonts, font_next) { 116 if (fl->font_flags == FONT_MANUAL || 117 fl->font_flags == FONT_BOOT) { 118 font = fl->font_data; 119 if (font->font == NULL && fl->font_load != NULL && 120 fl->font_name != NULL) { 121 font = fl->font_load(fl->font_name); 122 } 123 if (font == NULL || font->font == NULL) 124 font = NULL; 125 break; 126 } 127 } 128 129 if (font != NULL) { 130 *rows = (height - BORDER_PIXELS) / font->height; 131 *cols = (width - BORDER_PIXELS) / font->width; 132 return (font); 133 } 134 135 /* 136 * Find best font for these dimensions, or use default 137 * 138 * A 1 pixel border is the absolute minimum we could have 139 * as a border around the text window (BORDER_PIXELS = 2), 140 * however a slightly larger border not only looks better 141 * but for the fonts currently statically built into the 142 * emulator causes much better font selection for the 143 * normal range of screen resolutions. 144 */ 145 STAILQ_FOREACH(fl, &fonts, font_next) { 146 font = fl->font_data; 147 if ((((*rows * font->height) + BORDER_PIXELS) <= height) && 148 (((*cols * font->width) + BORDER_PIXELS) <= width)) { 149 if (font->font == NULL) { 150 if (fl->font_load != NULL && 151 fl->font_name != NULL) { 152 font = fl->font_load(fl->font_name); 153 } 154 if (font == NULL) 155 continue; 156 } 157 *rows = (height - BORDER_PIXELS) / font->height; 158 *cols = (width - BORDER_PIXELS) / font->width; 159 break; 160 } 161 font = NULL; 162 } 163 164 if (font == NULL) { 165 /* 166 * We have fonts sorted smallest last, try it before 167 * falling back to builtin. 168 */ 169 fl = STAILQ_LAST(&fonts, fontlist, font_next); 170 if (fl != NULL && fl->font_load != NULL && 171 fl->font_name != NULL) { 172 font = fl->font_load(fl->font_name); 173 } 174 if (font == NULL) 175 font = &DEFAULT_FONT_DATA; 176 177 *rows = (height - BORDER_PIXELS) / font->height; 178 *cols = (width - BORDER_PIXELS) / font->width; 179 } 180 181 return (font); 182 } 183 184 /* Binary search for the glyph. Return 0 if not found. */ 185 static uint16_t 186 font_bisearch(const struct font_map *map, uint32_t len, uint32_t src) 187 { 188 unsigned min, mid, max; 189 190 min = 0; 191 max = len - 1; 192 193 /* Empty font map. */ 194 if (len == 0) 195 return (0); 196 /* Character below minimal entry. */ 197 if (src < map[0].font_src) 198 return (0); 199 /* Optimization: ASCII characters occur very often. */ 200 if (src <= map[0].font_src + map[0].font_len) 201 return (src - map[0].font_src + map[0].font_dst); 202 /* Character above maximum entry. */ 203 if (src > map[max].font_src + map[max].font_len) 204 return (0); 205 206 /* Binary search. */ 207 while (max >= min) { 208 mid = (min + max) / 2; 209 if (src < map[mid].font_src) 210 max = mid - 1; 211 else if (src > map[mid].font_src + map[mid].font_len) 212 min = mid + 1; 213 else 214 return (src - map[mid].font_src + map[mid].font_dst); 215 } 216 217 return (0); 218 } 219 220 /* 221 * Return glyph bitmap. If glyph is not found, we will return bitmap 222 * for the first (offset 0) glyph. 223 */ 224 const uint8_t * 225 font_lookup(const struct font *vf, uint32_t c) 226 { 227 uint32_t src; 228 uint16_t dst; 229 size_t stride; 230 231 src = TEM_CHAR(c); 232 233 /* Substitute bold with normal if not found. */ 234 if (TEM_CHAR_ATTR(c) & TEM_ATTR_BOLD) { 235 dst = font_bisearch(vf->vf_map[VFNT_MAP_BOLD], 236 vf->vf_map_count[VFNT_MAP_BOLD], src); 237 if (dst != 0) 238 goto found; 239 } 240 dst = font_bisearch(vf->vf_map[VFNT_MAP_NORMAL], 241 vf->vf_map_count[VFNT_MAP_NORMAL], src); 242 243 found: 244 stride = howmany(vf->vf_width, 8) * vf->vf_height; 245 return (&vf->vf_bytes[dst * stride]); 246 } 247 248 /* 249 * bit_to_pix4 is for 4-bit frame buffers. It will write one output byte 250 * for each 2 bits of input bitmap. It inverts the input bits before 251 * doing the output translation, for reverse video. 252 * 253 * Assuming foreground is 0001 and background is 0000... 254 * An input data byte of 0x53 will output the bit pattern 255 * 00000001 00000001 00000000 00010001. 256 */ 257 258 void 259 font_bit_to_pix4( 260 struct font *f, 261 uint8_t *dest, 262 uint32_t c, 263 uint8_t fg_color, 264 uint8_t bg_color) 265 { 266 uint32_t row; 267 int byte; 268 int i; 269 const uint8_t *cp, *ul; 270 uint8_t data; 271 uint8_t nibblett; 272 int bytes_wide; 273 274 if (TEM_CHAR_ATTR(c) & TEM_ATTR_UNDERLINE) 275 ul = font_lookup(f, 0x0332); /* combining low line */ 276 else 277 ul = NULL; 278 279 cp = font_lookup(f, c); 280 bytes_wide = (f->vf_width + 7) / 8; 281 282 for (row = 0; row < f->vf_height; row++) { 283 for (byte = 0; byte < bytes_wide; byte++) { 284 if (ul == NULL) 285 data = *cp++; 286 else 287 data = *cp++ | *ul++; 288 for (i = 0; i < 4; i++) { 289 nibblett = (data >> ((3-i) * 2)) & 0x3; 290 switch (nibblett) { 291 case 0x0: 292 *dest++ = bg_color << 4 | bg_color; 293 break; 294 case 0x1: 295 *dest++ = bg_color << 4 | fg_color; 296 break; 297 case 0x2: 298 *dest++ = fg_color << 4 | bg_color; 299 break; 300 case 0x3: 301 *dest++ = fg_color << 4 | fg_color; 302 break; 303 } 304 } 305 } 306 } 307 } 308 309 /* 310 * bit_to_pix8 is for 8-bit frame buffers. It will write one output byte 311 * for each bit of input bitmap. It inverts the input bits before 312 * doing the output translation, for reverse video. 313 * 314 * Assuming foreground is 00000001 and background is 00000000... 315 * An input data byte of 0x53 will output the bit pattern 316 * 0000000 000000001 00000000 00000001 00000000 00000000 00000001 00000001. 317 */ 318 319 void 320 font_bit_to_pix8( 321 struct font *f, 322 uint8_t *dest, 323 uint32_t c, 324 uint8_t fg_color, 325 uint8_t bg_color) 326 { 327 uint32_t row; 328 int byte; 329 int i; 330 const uint8_t *cp, *ul; 331 uint8_t data; 332 int bytes_wide; 333 uint8_t mask; 334 int bitsleft, nbits; 335 336 if (TEM_CHAR_ATTR(c) & TEM_ATTR_UNDERLINE) 337 ul = font_lookup(f, 0x0332); /* combining low line */ 338 else 339 ul = NULL; 340 341 cp = font_lookup(f, c); 342 bytes_wide = (f->vf_width + 7) / 8; 343 344 for (row = 0; row < f->vf_height; row++) { 345 bitsleft = f->vf_width; 346 for (byte = 0; byte < bytes_wide; byte++) { 347 if (ul == NULL) 348 data = *cp++; 349 else 350 data = *cp++ | *ul++; 351 mask = 0x80; 352 nbits = MIN(8, bitsleft); 353 bitsleft -= nbits; 354 for (i = 0; i < nbits; i++) { 355 *dest++ = (data & mask ? fg_color: bg_color); 356 mask = mask >> 1; 357 } 358 } 359 } 360 } 361 362 /* 363 * bit_to_pix16 is for 16-bit frame buffers. It will write two output bytes 364 * for each bit of input bitmap. It inverts the input bits before 365 * doing the output translation, for reverse video. 366 * 367 * Assuming foreground is 11111111 11111111 368 * and background is 00000000 00000000 369 * An input data byte of 0x53 will output the bit pattern 370 * 371 * 00000000 00000000 372 * 11111111 11111111 373 * 00000000 00000000 374 * 11111111 11111111 375 * 00000000 00000000 376 * 00000000 00000000 377 * 11111111 11111111 378 * 11111111 11111111 379 * 380 */ 381 382 void 383 font_bit_to_pix16( 384 struct font *f, 385 uint16_t *dest, 386 uint32_t c, 387 uint16_t fg_color16, 388 uint16_t bg_color16) 389 { 390 uint32_t row; 391 int byte; 392 int i; 393 const uint8_t *cp, *ul; 394 uint16_t data, d; 395 int bytes_wide; 396 int bitsleft, nbits; 397 398 if (TEM_CHAR_ATTR(c) & TEM_ATTR_UNDERLINE) 399 ul = font_lookup(f, 0x0332); /* combining low line */ 400 else 401 ul = NULL; 402 403 cp = font_lookup(f, c); 404 bytes_wide = (f->vf_width + 7) / 8; 405 406 for (row = 0; row < f->vf_height; row++) { 407 bitsleft = f->vf_width; 408 for (byte = 0; byte < bytes_wide; byte++) { 409 if (ul == NULL) 410 data = *cp++; 411 else 412 data = *cp++ | *ul++; 413 nbits = MIN(8, bitsleft); 414 bitsleft -= nbits; 415 for (i = 0; i < nbits; i++) { 416 d = ((data << i) & 0x80 ? 417 fg_color16 : bg_color16); 418 *dest++ = d; 419 } 420 } 421 } 422 } 423 424 /* 425 * bit_to_pix24 is for 24-bit frame buffers. It will write three output bytes 426 * for each bit of input bitmap. It inverts the input bits before 427 * doing the output translation, for reverse video. 428 * 429 * Assuming foreground is 11111111 11111111 11111111 430 * and background is 00000000 00000000 00000000 431 * An input data byte of 0x53 will output the bit pattern 432 * 433 * 00000000 00000000 00000000 434 * 11111111 11111111 11111111 435 * 00000000 00000000 00000000 436 * 11111111 11111111 11111111 437 * 00000000 00000000 00000000 438 * 00000000 00000000 00000000 439 * 11111111 11111111 11111111 440 * 11111111 11111111 11111111 441 * 442 */ 443 444 void 445 font_bit_to_pix24( 446 struct font *f, 447 uint8_t *dest, 448 uint32_t c, 449 uint32_t fg_color32, 450 uint32_t bg_color32) 451 { 452 uint32_t row; 453 int byte; 454 int i; 455 const uint8_t *cp, *ul; 456 uint32_t data, d; 457 int bytes_wide; 458 int bitsleft, nbits; 459 460 if (TEM_CHAR_ATTR(c) & TEM_ATTR_UNDERLINE) 461 ul = font_lookup(f, 0x0332); /* combining low line */ 462 else 463 ul = NULL; 464 465 cp = font_lookup(f, c); 466 bytes_wide = (f->vf_width + 7) / 8; 467 468 for (row = 0; row < f->vf_height; row++) { 469 bitsleft = f->vf_width; 470 for (byte = 0; byte < bytes_wide; byte++) { 471 if (ul == NULL) 472 data = *cp++; 473 else 474 data = *cp++ | *ul++; 475 476 nbits = MIN(8, bitsleft); 477 bitsleft -= nbits; 478 for (i = 0; i < nbits; i++) { 479 d = ((data << i) & 0x80 ? 480 fg_color32 : bg_color32); 481 *dest++ = d & 0xff; 482 *dest++ = (d >> 8) & 0xff; 483 *dest++ = (d >> 16) & 0xff; 484 } 485 } 486 } 487 } 488 489 /* 490 * bit_to_pix32 is for 32-bit frame buffers. It will write four output bytes 491 * for each bit of input bitmap. It inverts the input bits before 492 * doing the output translation, for reverse video. Note that each 493 * 24-bit RGB value is finally stored in a 32-bit unsigned int, with the 494 * high-order byte set to zero. 495 * 496 * Assuming foreground is 00000000 11111111 11111111 11111111 497 * and background is 00000000 00000000 00000000 00000000 498 * An input data byte of 0x53 will output the bit pattern 499 * 500 * 00000000 00000000 00000000 00000000 501 * 00000000 11111111 11111111 11111111 502 * 00000000 00000000 00000000 00000000 503 * 00000000 11111111 11111111 11111111 504 * 00000000 00000000 00000000 00000000 505 * 00000000 00000000 00000000 00000000 506 * 00000000 11111111 11111111 11111111 507 * 00000000 11111111 11111111 11111111 508 * 509 */ 510 511 void 512 font_bit_to_pix32( 513 struct font *f, 514 uint32_t *dest, 515 uint32_t c, 516 uint32_t fg_color32, 517 uint32_t bg_color32) 518 { 519 uint32_t row; 520 int byte; 521 int i; 522 const uint8_t *cp, *ul; 523 uint32_t data; 524 int bytes_wide; 525 int bitsleft, nbits; 526 527 if (TEM_CHAR_ATTR(c) & TEM_ATTR_UNDERLINE) 528 ul = font_lookup(f, 0x0332); /* combining low line */ 529 else 530 ul = NULL; 531 532 cp = font_lookup(f, c); 533 bytes_wide = (f->vf_width + 7) / 8; 534 535 for (row = 0; row < f->vf_height; row++) { 536 bitsleft = f->vf_width; 537 for (byte = 0; byte < bytes_wide; byte++) { 538 if (ul == NULL) 539 data = *cp++; 540 else 541 data = *cp++ | *ul++; 542 nbits = MIN(8, bitsleft); 543 bitsleft -= nbits; 544 for (i = 0; i < nbits; i++) { 545 *dest++ = ((data << i) & 0x80 ? 546 fg_color32 : bg_color32); 547 } 548 } 549 } 550 } 551