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