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/font.h>
38 #include <sys/sysmacros.h>
39
40 /*
41 * Fonts are statically linked with this module. At some point an
42 * RFE might be desireable to allow dynamic font loading. The
43 * original intention to facilitate dynamic fonts can be seen
44 * by examining the data structures and set_font(). As much of
45 * the original code is retained but modified to be suited for
46 * traversing a list of static fonts.
47 */
48
49 /*
50 * Must be sorted by font size in descending order
51 */
52 struct fontlist fonts[] = {
53 { &font_data_12x22, NULL },
54 { &font_data_8x16, NULL },
55 { &font_data_7x14, NULL },
56 { &font_data_6x10, NULL },
57 { NULL, NULL }
58 };
59
60 void
61 set_font(struct font *f, short *rows, short *cols, short height, short width)
62 {
63 bitmap_data_t *font_selected = NULL;
64 struct fontlist *fl;
65 int i;
66
67 /*
68 * Find best font for these dimensions, or use default
69 *
70 * A 1 pixel border is the absolute minimum we could have
71 * as a border around the text window (BORDER_PIXELS = 2),
72 * however a slightly larger border not only looks better
73 * but for the fonts currently statically built into the
74 * emulator causes much better font selection for the
75 * normal range of screen resolutions.
76 */
77 for (fl = fonts; fl->data; fl++) {
78 if ((((*rows * fl->data->height) + BORDER_PIXELS) <= height) &&
79 (((*cols * fl->data->width) + BORDER_PIXELS) <= width)) {
80 font_selected = fl->data;
81 break;
82 }
83 }
84 /*
85 * The minus 2 is to make sure we have at least a 1 pixel
86 * border around the entire screen.
87 */
88 if (font_selected == NULL) {
89 if (((*rows * DEFAULT_FONT_DATA.height) > height) ||
90 ((*cols * DEFAULT_FONT_DATA.width) > width)) {
91 *rows = (height - 2) / DEFAULT_FONT_DATA.height;
92 *cols = (width - 2) / DEFAULT_FONT_DATA.width;
93 }
94 font_selected = &DEFAULT_FONT_DATA;
95 }
96
97 f->width = font_selected->width;
98 f->height = font_selected->height;
99
100 for (i = 0; i < ENCODED_CHARS; i++)
101 f->char_ptr[i] = font_selected->encoding[i];
102
103 f->image_data = font_selected->image;
104
105 }
106
107 /*
108 * bit_to_pix4 is for 4-bit frame buffers. It will write one output byte
109 * for each 2 bits of input bitmap. It inverts the input bits before
110 * doing the output translation, for reverse video.
111 *
112 * Assuming foreground is 0001 and background is 0000...
113 * An input data byte of 0x53 will output the bit pattern
114 * 00000001 00000001 00000000 00010001.
115 */
116
117 void
118 font_bit_to_pix4(
119 struct font *f,
120 uint8_t *dest,
121 uint8_t c,
122 uint8_t fg_color,
123 uint8_t bg_color)
124 {
125 int row;
126 int byte;
127 int i;
128 uint8_t *cp;
129 uint8_t data;
130 uint8_t nibblett;
131 int bytes_wide;
132
133 cp = f->char_ptr[c];
134 bytes_wide = (f->width + 7) / 8;
135
136 for (row = 0; row < f->height; row++) {
137 for (byte = 0; byte < bytes_wide; byte++) {
138 data = *cp++;
139 for (i = 0; i < 4; i++) {
140 nibblett = (data >> ((3-i) * 2)) & 0x3;
141 switch (nibblett) {
142 case 0x0:
143 *dest++ = bg_color << 4 | bg_color;
144 break;
145 case 0x1:
146 *dest++ = bg_color << 4 | fg_color;
147 break;
148 case 0x2:
149 *dest++ = fg_color << 4 | bg_color;
150 break;
151 case 0x3:
152 *dest++ = fg_color << 4 | fg_color;
153 break;
154 }
155 }
156 }
157 }
158 }
159
160 /*
161 * bit_to_pix8 is for 8-bit frame buffers. It will write one output byte
162 * for each bit of input bitmap. It inverts the input bits before
163 * doing the output translation, for reverse video.
164 *
165 * Assuming foreground is 00000001 and background is 00000000...
166 * An input data byte of 0x53 will output the bit pattern
167 * 0000000 000000001 00000000 00000001 00000000 00000000 00000001 00000001.
168 */
169
170 void
171 font_bit_to_pix8(
172 struct font *f,
173 uint8_t *dest,
174 uint8_t c,
175 uint8_t fg_color,
176 uint8_t bg_color)
177 {
178 int row;
179 int byte;
180 int i;
181 uint8_t *cp;
182 uint8_t data;
183 int bytes_wide;
184 uint8_t mask;
185 int bitsleft, nbits;
186
187 cp = f->char_ptr[c];
188 bytes_wide = (f->width + 7) / 8;
189
190 for (row = 0; row < f->height; row++) {
191 bitsleft = f->width;
192 for (byte = 0; byte < bytes_wide; byte++) {
193 data = *cp++;
194 mask = 0x80;
195 nbits = MIN(8, bitsleft);
196 bitsleft -= nbits;
197 for (i = 0; i < nbits; i++) {
198 *dest++ = (data & mask ? fg_color: bg_color);
199 mask = mask >> 1;
200 }
201 }
202 }
203 }
204
205 /*
206 * bit_to_pix24 is for 24-bit frame buffers. It will write four output bytes
207 * for each bit of input bitmap. It inverts the input bits before
208 * doing the output translation, for reverse video. Note that each
209 * 24-bit RGB value is finally stored in a 32-bit unsigned int, with the
210 * high-order byte set to zero.
211 *
212 * Assuming foreground is 00000000 11111111 11111111 11111111
213 * and background is 00000000 00000000 00000000 00000000
214 * An input data byte of 0x53 will output the bit pattern
215 *
216 * 00000000 00000000 00000000 00000000
217 * 00000000 11111111 11111111 11111111
218 * 00000000 00000000 00000000 00000000
219 * 00000000 11111111 11111111 11111111
220 * 00000000 00000000 00000000 00000000
221 * 00000000 00000000 00000000 00000000
222 * 00000000 11111111 11111111 11111111
223 * 00000000 11111111 11111111 11111111
224 *
225 */
226
227 void
228 font_bit_to_pix24(
229 struct font *f,
230 uint32_t *dest,
231 uint8_t c,
232 uint32_t fg_color32,
233 uint32_t bg_color32)
234 {
235 int row;
236 int byte;
237 int i;
238 uint8_t *cp;
239 uint32_t data;
240 int bytes_wide;
241 int bitsleft, nbits;
242
243 cp = f->char_ptr[c];
244 bytes_wide = (f->width + 7) / 8;
245
246 for (row = 0; row < f->height; row++) {
247 bitsleft = f->width;
248 for (byte = 0; byte < bytes_wide; byte++) {
249 data = *cp++;
250 nbits = MIN(8, bitsleft);
251 bitsleft -= nbits;
252 for (i = 0; i < nbits; i++) {
253 *dest++ = ((data << i) & 0x80 ?
254 fg_color32 : bg_color32);
255 }
256 }
257 }
258 }
|
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 }
|