summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcflip <cflip@cflip.net>2023-01-10 17:31:27 -0700
committercflip <cflip@cflip.net>2023-01-10 17:31:27 -0700
commit3eaf3418928e9e9eac271961a983b720a7989972 (patch)
treebc2c4995aadbf5c1d0a8bf9f6df628d0b4647823
parent0cd5d2b28f7529f4f9f7b31b9f54e76ada76d9b7 (diff)
Parse unicode tables in PSF fonts
-rw-r--r--font.c36
-rw-r--r--font.h5
-rw-r--r--window.c12
3 files changed, 44 insertions, 9 deletions
diff --git a/font.c b/font.c
index 01b2c43..e2c1a74 100644
--- a/font.c
+++ b/font.c
@@ -1,6 +1,7 @@
#include "font.h"
#include <assert.h>
+#include <limits.h>
#include <stdlib.h>
/* Create a texture atlas containing all of the glyphs in a font. */
@@ -45,8 +46,14 @@ PSFFont font_load(const char *filename)
FILE *fp = fopen(filename, "rb");
+ fseek(fp, 0, SEEK_END);
+ size_t filesize = ftell(fp);
+ fseek(fp, 0, SEEK_SET);
+
fread(&font.magic, 4, 1, fp);
- assert(font.magic == PSF_MAGIC_NUMBER);
+ if (font.magic != PSF_MAGIC_NUMBER) {
+ printf("%x: Font '%s' header does not contain expected value.\n", font.magic, filename);
+ }
fread(&font.version, 4, 1, fp);
fread(&font.header_size, 4, 1, fp);
@@ -56,12 +63,35 @@ PSFFont font_load(const char *filename)
fread(&font.height, 4, 1, fp);
fread(&font.width, 4, 1, fp);
- /* TODO: Implement unicode translation table. */
-
size_t glyph_buffer_size = font.num_glyphs * font.bytes_per_glyph;
font.glyph_data = malloc(glyph_buffer_size);
fread(font.glyph_data, font.bytes_per_glyph, font.num_glyphs, fp);
+ font.unicode_desc = NULL;
+ if (font.flags == PSF_FLAG_UNICODE) {
+ size_t current_pos = ftell(fp);
+ size_t bytes_left = filesize - current_pos;
+
+ /* Store the file's unicode information in a buffer. */
+ char *desc = malloc(bytes_left);
+ fread(desc, bytes_left, 1, fp);
+
+ /* Create a buffer in our object to map character codes to glyphs */
+ font.unicode_desc = calloc(USHRT_MAX, 2);
+
+ int glyph_index = 0;
+ unsigned char letter = 0;
+ for (int i = 0; i < bytes_left; i++) {
+ unsigned char uc = desc[i];
+ if (uc == 0xff) {
+ font.unicode_desc[letter] = glyph_index;
+ glyph_index++;
+ } else {
+ letter = uc;
+ }
+ }
+ }
+
fclose(fp);
printf("Loaded a font with %d glyphs of size %dx%d (%d bytes per glyph)\n",
diff --git a/font.h b/font.h
index 4f82fca..c1ae680 100644
--- a/font.h
+++ b/font.h
@@ -4,9 +4,7 @@
#include <SDL2/SDL.h>
#define PSF_MAGIC_NUMBER 0x864ab572
-
-typedef struct {
-} PSFFontHeader;
+#define PSF_FLAG_UNICODE 1
typedef struct {
uint32_t magic;
@@ -18,6 +16,7 @@ typedef struct {
uint32_t height;
uint32_t width;
uint8_t *glyph_data;
+ uint16_t *unicode_desc;
} PSFFont;
PSFFont font_load(const char *);
diff --git a/window.c b/window.c
index 1e6d5f2..7f29abe 100644
--- a/window.c
+++ b/window.c
@@ -97,15 +97,21 @@ static void draw_font_text(struct append_buffer *buffer)
for (int i = 0; i < buffer->length; i++) {
const char letter = buffer->buffer[i];
- if (letter > 128) {
- printf("TODO: Non-ASCII characters are not currently supported.\n");
+ if (letter == ' ') {
+ dstrect.x += font.width;
continue;
}
+
+ int glyph_index = letter;
+ if (font.unicode_desc != NULL) {
+ glyph_index = font.unicode_desc[glyph_index];
+ }
+
dstrect.w = font.width;
dstrect.h = font.height;
- srcrect.x = letter * 8;
+ srcrect.x = glyph_index * 8;
srcrect.y = 0;
srcrect.w = font.width;
srcrect.h = font.height;