diff options
author | cflip <cflip@cflip.net> | 2023-01-10 17:31:27 -0700 |
---|---|---|
committer | cflip <cflip@cflip.net> | 2023-01-10 17:31:27 -0700 |
commit | 3eaf3418928e9e9eac271961a983b720a7989972 (patch) | |
tree | bc2c4995aadbf5c1d0a8bf9f6df628d0b4647823 | |
parent | 0cd5d2b28f7529f4f9f7b31b9f54e76ada76d9b7 (diff) |
Parse unicode tables in PSF fonts
-rw-r--r-- | font.c | 36 | ||||
-rw-r--r-- | font.h | 5 | ||||
-rw-r--r-- | window.c | 12 |
3 files changed, 44 insertions, 9 deletions
@@ -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", @@ -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 *); @@ -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; |