diff options
Diffstat (limited to 'src/user/libfont')
-rw-r--r-- | src/user/libfont/bdf.c | 99 | ||||
-rw-r--r-- | src/user/libfont/bdf.h | 8 | ||||
-rw-r--r-- | src/user/libfont/filist.c | 33 | ||||
-rw-r--r-- | src/user/libfont/filist.h | 8 | ||||
-rw-r--r-- | src/user/libfont/fonts.c | 66 |
5 files changed, 214 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 diff --git a/src/user/libfont/bdf.h b/src/user/libfont/bdf.h new file mode 100644 index 0000000..4ed4189 --- /dev/null +++ b/src/user/libfont/bdf.h @@ -0,0 +1,8 @@ +#ifndef LIBFONT_BDF_H +#define LIBFONT_BDF_H + +#include <stdbool.h> + +bool try_load_bdf(const char *path, struct font_info *into); + +#endif
\ No newline at end of file diff --git a/src/user/libfont/filist.c b/src/user/libfont/filist.c new file mode 100644 index 0000000..ae24429 --- /dev/null +++ b/src/user/libfont/filist.c @@ -0,0 +1,33 @@ +#include <libfont/fonts.h> +#include <knob/block.h> +#include <knob/heap.h> + +struct dict_entry { + char *name; + struct font_info *fi; + struct dict_entry *prev; +} *last_entry = 0; + +__attribute__ ((pure)) +struct font_info *find_entry(const char *name) { + for (struct dict_entry *i = last_entry; i; i = i->prev) + if (strequ(i->name, name)) + return i->fi; + return 0; +} + +struct font_info *new_entry(const char *name) { + struct dict_entry *const nde = get_block(sizeof(struct dict_entry)); + nde->name = strdup(name); + nde->fi = get_block(sizeof(struct font_info)); + nde->prev = last_entry; + last_entry = nde; + return nde->fi; +} + +void del_last() {//only called when last_entry isn't 0 + free_block(last_entry->name); + free_block(last_entry->fi); + free_block(last_entry); + last_entry = last_entry->prev; +}
\ No newline at end of file diff --git a/src/user/libfont/filist.h b/src/user/libfont/filist.h new file mode 100644 index 0000000..c78c640 --- /dev/null +++ b/src/user/libfont/filist.h @@ -0,0 +1,8 @@ +#ifndef LIBFONT_FILIST_H +#define LIBFONT_FILIST_H + +struct font_info *find_entry(const char *name) __attribute__ ((pure)); +struct font_info *new_entry(const char *name); +void del_last(); + +#endif
\ No newline at end of file diff --git a/src/user/libfont/fonts.c b/src/user/libfont/fonts.c new file mode 100644 index 0000000..1692992 --- /dev/null +++ b/src/user/libfont/fonts.c @@ -0,0 +1,66 @@ +#include <libfont/fonts.h> +#include <knob/format.h> +#include <knob/block.h> +#include <knob/heap.h> +#include <knob/file.h> + +#include "filist.h" +#include "bdf.h" + +#define FONT_PATH "fonts/" +#define FONT_PATH_L 6 + +struct font_loader_t { + const char *ext; + bool (*func)(const char *, struct font_info *); +} font_loaders[] = { + { .ext = ".bdf", + .func = try_load_bdf + }, + { .ext = "" + } +}; + +struct font_info *get_font(const char *name) { + struct font_info *font = find_entry(name); + if (font) + return font; + font = new_entry(name); + if (!font) + return 0;//out of memory? + + const uint32_t name_len = strlen(name); + for (struct font_loader_t *i = font_loaders; i->ext[0]; ++i) { + char *buf = get_block(FONT_PATH_L + name_len + strlen(i->ext) + 1); + blockcpy(buf, FONT_PATH, FONT_PATH_L); + blockcpy(buf + FONT_PATH_L, name, name_len); + strcpy(buf + FONT_PATH_L + name_len, i->ext); + struct file *f = open_file(buf); + if (!f) { + free_block(buf); + continue; + } + syslogf("[libfont] Loading %s%s...", name, i->ext); + if (i->func(buf, font)) { + close_file(f); + free_block(buf); + syslogf("[libfont] Loaded %s%s.", name, i->ext); + return font; + } + close_file(f); + free_block(buf); + syslogf("[libfont] Failed to load %s%s.", name, i->ext); + } + del_last(); + return 0; +} + +void put_char(const struct font_info *font, char ch, uint8_t *pb_ptr, uint32_t pb_pitch, uint8_t bg, uint8_t fg) { +//char *const msg = format("put_char(font = 0x%x, ch = '%c', pb_ptr = 0x%x, pb_pitch = %u, bg = 0x%2x, fg = 0x%2x);", font, ch, pb_ptr, pb_pitch, bg, fg); +//_system_log(msg); +//free_block(msg); + const bool *const bitmap = font->bitmaps[(uint8_t)ch] ? font->bitmaps[(uint8_t)ch] : font->bitmaps[0]; + for (uint32_t y = 0; y < font->char_height; ++y) + for (uint32_t x = 0; x < font->char_width; ++x) + pb_ptr[y * pb_pitch + x] = bitmap[y * font->char_width + x] ? fg : bg; +}
\ No newline at end of file |