gterm: support different font sizes

This commit is contained in:
Hannu Hartikainen 2021-08-18 15:06:55 +03:00
parent 867b4a5fa6
commit a8a8af4c5f
4 changed files with 40 additions and 9 deletions

View File

@ -56,8 +56,9 @@ Some keys take *URIs* as values; these are described in the next section.
* `GRAPHICS` - If set to `yes`, use a graphical framebuffer for the boot menu, else use text mode. Ignored with Limine UEFI, forced to `yes`.
* `MENU_RESOLUTION` - Specify screen resolution to be used by the Limine menu in the form `<width>x<height>`. This will *only* affect the menu, not any booted OS. If not specified, Limine will pick a resolution automatically. If the resolution is not available, Limine will pick another one automatically. Ignored if `GRAPHICS` is not `yes`.
* `MENU_BRANDING` - A string that will be displayed on top of the Limine menu.
* `MENU_FONT` - URI path to a font file to be used instead of the default one for the menu and terminal. The font file must be a code page 437 character set comprised of 256 consecutive 8x16 glyphs bitmaps (4096 byte font file). Each glyph's bitmap must be expressed left to right (1 byte per row), and top to bottom (16 bytes per whole glyph).
* `MENU_FONT` - URI path to a font file to be used instead of the default one for the menu and terminal. The font file must be a code page 437 character set comprised of 256 consecutive glyph bitmaps. Each glyph's bitmap must be expressed left to right (1 byte per row), and top to bottom (16 bytes per whole glyph by default; see `MENU_FONT_SIZE`). See e.g. the [VGA text mode font collection](https://github.com/viler-int10h/vga-text-mode-fonts) for fonts.
* `TERMINAL_FONT` - Alias of `MENU_FONT`.
* `MENU_FONT_SIZE` - The size of the font in dots, which must correspond to the font file or the display will be garbled. Note that glyphs are always one byte wide, and columns over 8 are empty. Many fonts may be used in both 8- and 9-dot wide variants. Defaults to `8x16`.
* `THEME_COLOURS` - Specifies the colour palette used by the terminal (AARRGGBB). It is a `;` separated array of 10 colours: black, red, green, brown, blue, magenta, cyan, gray, background, and foreground respectively. While an alpha transparency value can be specified for every colour, it is ignored for all but background. Ignored if `GRAPHICS` is not `yes`.
* `THEME_COLORS` - Alias of `THEME_COLOURS`.
* `THEME_BACKGROUND` - Alias of the background value in `THEME_COLOURS`.

View File

@ -41,7 +41,9 @@ bool parse_resolution(size_t *width, size_t *height, size_t *bpp, const char *bu
if (res[2] == 0)
res[2] = 32;
*width = res[0], *height = res[1], *bpp = res[2];
*width = res[0], *height = res[1];
if (bpp != NULL)
*bpp = res[2];
return true;
}

View File

@ -10,10 +10,14 @@
#include <lib/fb.h>
#include <mm/pmm.h>
#define VGA_FONT_WIDTH 8
#define VGA_FONT_HEIGHT 16
static size_t VGA_FONT_WIDTH = 8;
static size_t VGA_FONT_HEIGHT = 16;
#define VGA_FONT_GLYPHS 256
#define VGA_FONT_MAX (VGA_FONT_HEIGHT * VGA_FONT_GLYPHS)
// Maximum allowed font size in bytes. 16kB should be enough as 9x32 is the
// largest font I've seen, and that would take 9*32 * 256 * 1/8 byte =
// 9216 bytes.
#define VGA_FONT_MAX 16384
struct fb_info fbinfo;
static uint32_t *gterm_framebuffer;
@ -640,21 +644,39 @@ bool gterm_init(size_t *_rows, size_t *_cols, size_t width, size_t height) {
gterm_bpp = fbinfo.framebuffer_bpp;
gterm_pitch = fbinfo.framebuffer_pitch;
size_t font_width = VGA_FONT_WIDTH, font_height = VGA_FONT_HEIGHT;
char *menu_font_size = config_get_value(NULL, 0, "MENU_FONT_SIZE");
if (menu_font_size != NULL)
parse_resolution(&font_width, &font_height, NULL, menu_font_size);
size_t font_bytes = (font_width * font_height * VGA_FONT_GLYPHS) / 8;
if (vga_font_bits == NULL) {
vga_font_bits = ext_mem_alloc(VGA_FONT_MAX);
memcpy(vga_font_bits, (void *)_binary_font_bin_start, VGA_FONT_MAX);
}
char *menu_font = config_get_value(NULL, 0, "MENU_FONT");
if (menu_font == NULL)
menu_font = config_get_value(NULL, 0, "TERMINAL_FONT");
char *menu_font = NULL;
if (font_bytes > VGA_FONT_MAX) {
print("Font would be too large (%x bytes, %x bytes allowed). Not loading.\n");
} else {
menu_font = config_get_value(NULL, 0, "MENU_FONT");
if (menu_font == NULL)
menu_font = config_get_value(NULL, 0, "TERMINAL_FONT");
}
if (menu_font != NULL) {
struct file_handle f;
if (!uri_open(&f, menu_font)) {
print("menu: Could not open font file.\n");
} else {
fread(&f, vga_font_bits, 0, VGA_FONT_MAX);
if (fread(&f, vga_font_bits, 0, font_bytes) == 0) {
VGA_FONT_WIDTH = font_width;
VGA_FONT_HEIGHT = font_height;
}
}
}
@ -666,8 +688,13 @@ bool gterm_init(size_t *_rows, size_t *_cols, size_t width, size_t height) {
uint8_t *glyph = &vga_font_bits[i * VGA_FONT_HEIGHT];
for (size_t y = 0; y < VGA_FONT_HEIGHT; y++) {
// NOTE: the characters in VGA fonts are always at most
// one byte wide. 9 dot wide fonts have 8 dots and one
// empty column, except characters 0xC0-0xDF replicate
// column 9 in Line Graphics Mode. (TODO: implement that)
for (size_t x = 0; x < VGA_FONT_WIDTH; x++) {
size_t offset = i * VGA_FONT_HEIGHT * VGA_FONT_WIDTH + y * VGA_FONT_WIDTH + x;
if ((glyph[y] & (0x80 >> x))) {
vga_font_bool[offset] = true;
} else {

View File

@ -79,6 +79,7 @@ static const char *VALID_KEYS[] = {
"MENU_RESOLUTION",
"MENU_BRANDING",
"MENU_FONT",
"MENU_FONT_SIZE",
"TERMINAL_FONT",
"THEME_COLOURS",
"THEME_COLORS",