diff options
Diffstat (limited to 'src/user/libfont/bdf.c')
-rw-r--r-- | src/user/libfont/bdf.c | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/src/user/libfont/bdf.c b/src/user/libfont/bdf.c new file mode 100644 index 0000000..2c19a15 --- /dev/null +++ b/src/user/libfont/bdf.c @@ -0,0 +1,99 @@ +#include <libfont/fonts.h> + +#include <knob/format.h> +#include <knob/panic.h> +#include <knob/block.h> +#include <knob/heap.h> +#include <knob/file.h> + +#include <stdbool.h> +#include <stdint.h> + +#define LINE_BUF_SIZE 1000 +char line_buf[LINE_BUF_SIZE]; + +static inline uint8_t hex_to_n(char ch) { + return ch - (ch >= 'A' ? 'A' - 10 : '0'); +} + +//very minimal implementation +bool try_load_bdf(const char *path, struct font_info *into) { + struct file *f = open_file(path); + if (!f) + PANIC("Can't open font file sent by get_font."); + + read_line_from_file(f, line_buf, LINE_BUF_SIZE - 1); + if (!strequ(line_buf, "STARTFONT 2.1")) { + close_file(f); + return false; + } + + for (uint16_t i = 0; i < 256; ++i) + into->bitmaps[i] = 0; + into->space_height = -1; + into->space_width = -1; + into->char_height = -1; + into->char_width = -1; + + uint32_t current = 0; + + while (read_line_from_file(f, line_buf, LINE_BUF_SIZE - 1)) { + if (blockequ(line_buf, "FONTBOUNDINGBOX ", 16)) { + uint32_t n; + uint32_t l = try_swtou(line_buf + 16, &n); + if (!l) + goto bad_format; + into->space_width = n; + into->char_width = n; + l = try_swtou(line_buf + 16 + l, &n); + if (!l) + goto bad_format; + into->space_height = n; + into->char_height = n; + } + else if (blockequ(line_buf, "ENCODING ", 9)) { + if (!try_swtou(line_buf + 9, ¤t)) + goto bad_format; + } + else if (strequ(line_buf, "BITMAP")) { + if (current >= 256) + continue; + bool *bm = get_block(into->char_height * into->char_width); + if (!bm) + PANIC("could not allocate memory for font character bitmap"); + into->bitmaps[current] = bm; + + for (uint32_t y = 0; y < into->char_height; ++y) { + read_line_from_file(f, line_buf, LINE_BUF_SIZE - 1); + for (uint32_t x = 0; x < into->char_width; ++x) + bm[y * into->char_width + x] = (hex_to_n(line_buf[x / 4]) >> (3 - x % 4)) & 1; + } + } + } + + close_file(f); + f = 0; + + if ((into->char_height == -1) || + (into->char_width == -1) || + (into->space_height == -1) || + (into->space_width == -1)) + goto bad_format; + + if (!into->bitmaps[0]) { + const uint32_t bytes = (into->char_height * into->char_width - 1) / 8 + 1; + into->bitmaps[0] = get_block(bytes); + for (uint32_t i = 0; i < bytes; ++i) + into->bitmaps[0][i] = 0b01011010; + } + + return true; + +bad_format: + if (f) + close_file(f); + for (uint16_t i = 0; i < 256; ++i) + if (into->bitmaps[i]) + free_block(into->bitmaps[i]); + return false; +}
\ No newline at end of file |