summaryrefslogtreecommitdiff
path: root/src/user/libfont
diff options
context:
space:
mode:
authorBenji Dial <benji6283@gmail.com>2021-01-24 12:00:11 -0500
committerBenji Dial <benji6283@gmail.com>2021-01-24 12:00:11 -0500
commitbce944d1498eaa3b6940ee234c863b3548a66b37 (patch)
treeea40c087ab4f0f236aee8d158cf68550f5209f72 /src/user/libfont
parentca731aa747214919df7b3dfe3478dbe787ce5b68 (diff)
downloadportland-os-bce944d1498eaa3b6940ee234c863b3548a66b37.tar.gz
graphics!
Diffstat (limited to 'src/user/libfont')
-rw-r--r--src/user/libfont/bdf.c99
-rw-r--r--src/user/libfont/bdf.h8
-rw-r--r--src/user/libfont/filist.c33
-rw-r--r--src/user/libfont/filist.h8
-rw-r--r--src/user/libfont/fonts.c66
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, &current))
+ 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