diff options
| author | Menase Teshale <osome3717@gmail.com> | 2026-08-26 04:04:45 +0300 |
|---|---|---|
| committer | Menase Teshale <osome3717@gmail.com> | 2026-08-26 04:04:45 +0300 |
| commit | bf502b35ec7f470fbd251e8c51c1e60f22f60dbd (patch) | |
| tree | 6b7c1a88c9e393782655049b3a41bfe6e0240428 /src | |
| parent | 790249cc59bdf646ee38a081ebe392c33ae5b732 (diff) | |
Loading fonts hopefully completed!
Diffstat (limited to 'src')
| -rw-r--r-- | src/font.c | 180 | ||||
| -rw-r--r-- | src/font.h | 4 |
2 files changed, 165 insertions, 19 deletions
@@ -3,6 +3,8 @@ #include <stdio.h> #include <errno.h> #include <string.h> +#include <limits.h> +#include <SDL3_image/SDL_image.h> #define FILE_NAME_SIZE 300 @@ -30,13 +32,29 @@ int get_string_parameter(const char* line, const char* parameter, const char** s return length; } -char parse_character_tag(const char* character_tag) { +unsigned char parse_character_tag(const char* character_tag) { if (strncmp(character_tag, "space", 5) == 0) return ' '; return character_tag[0]; } +void extract_dir_name(const char* filename, char dir_name_buffer[FILE_NAME_SIZE]) { + strcpy(dir_name_buffer, ""); + + const char* head = filename; + const char* next; + + while ((next = strchr(head+1, '/')) != NULL) { + head=next; + } + + int dir_name_length = SDL_min(head - filename, FILE_NAME_SIZE-1); + strncpy(dir_name_buffer, filename, dir_name_length); + + dir_name_buffer[dir_name_length] = '\0'; +} + bool get_int_parameter(const char* line, const char* parameter, int* value) { const char* start = strstr(line, parameter); if (start == NULL) { @@ -60,7 +78,7 @@ bool get_int_parameter(const char* line, const char* parameter, int* value) { return true; } -bool load_sprite_font(const char* filename, sprite_font* font) { +bool load_sprite_font(SDL_Renderer* renderer, const char* filename, sprite_font* font) { if (font->characters || font->spritesheet) { SDL_Log("Trying to reallocate font causing memory leak, exitting!"); exit(EXIT_FAILURE); @@ -68,20 +86,20 @@ bool load_sprite_font(const char* filename, sprite_font* font) { FILE* f = fopen(filename, "r"); if (f == NULL) { - SDL_Log("Failed to open sprite font file %s, error: %s, exitting!", + SDL_Log("Failed to open sprite font file %s, error: %s!", filename, strerror(errno) ); - exit(EXIT_FAILURE); + return false; } char line[PARSER_LINE_SIZE]; if (fgets(line, sizeof(line), f) == NULL || strncmp(line, "info", 4) != 0) { - SDL_Log("File %s is not a valid font file, exitting!", + SDL_Log("File %s is not a valid font file!", filename); fclose(f); - exit(EXIT_FAILURE); + return false; } char font_name[FONT_NAME_SIZE]; @@ -97,7 +115,12 @@ bool load_sprite_font(const char* filename, sprite_font* font) { int char_size = 0, char_count = 0; font_char* characters_unarranged = NULL; + unsigned char smallest_char = UCHAR_MAX; + unsigned char largest_char = 0; + + char sprite_file_name[FILE_NAME_SIZE] = ""; while (fgets(line, PARSER_LINE_SIZE, f) != NULL) { + font_char* temp; if (strncmp(line, "chars", 5) == 0) { int total_char_count; @@ -106,15 +129,41 @@ bool load_sprite_font(const char* filename, sprite_font* font) { continue; char_size = total_char_count; - characters_unarranged = + temp = realloc(characters_unarranged, char_size * sizeof(font_char)); - if (characters_unarranged == NULL) { - SDL_Log("Failed to allocate space while loading font %s, error %s, exitting!", + if (temp == NULL) { + SDL_Log("Failed to allocate space while loading font %s, error %s", filename, strerror(errno)); - exit(EXIT_FAILURE); + + if (characters_unarranged != NULL) { + free(characters_unarranged); + } + + fclose(f); + return false; + } + + characters_unarranged = temp; + } + + //Only one page supported + else if (strcmp(sprite_file_name, "") == 0 && strncmp(line, "page", 4) == 0) { + const char* sprite_fname_start; + int sprite_fname_length = + SDL_min(get_string_parameter(line, "file=", &sprite_fname_start), + FONT_NAME_SIZE-1 + ); + + if (sprite_fname_length <= 0) { + SDL_Log("Malformed spritesheet file name in font file %s", + filename); + continue; } + + strncpy(sprite_file_name, sprite_fname_start, sprite_fname_length); + font_name[sprite_fname_length] = '\0'; } else if (strncmp(line, "char", 4) == 0) { @@ -155,17 +204,33 @@ bool load_sprite_font(const char* filename, sprite_font* font) { continue; new_font_char.character = parse_character_tag(character_tag); + if (new_font_char.character < smallest_char) { + smallest_char = new_font_char.character; + } + + if (new_font_char.character > largest_char) { + largest_char = new_font_char.character; + } + if (char_count >= char_size) { char_size = char_count+1; - characters_unarranged = + temp = realloc(characters_unarranged, char_size * sizeof(font_char)); - } - if (characters_unarranged == NULL) { - SDL_Log("Failed to allocate space while loading font %s, error %s, exitting!", - filename, - strerror(errno)); - exit(EXIT_FAILURE); + if (temp == NULL) { + SDL_Log("Failed to allocate space while loading font %s, error %s", + filename, + strerror(errno)); + + if (characters_unarranged != NULL) { + free(characters_unarranged); + } + + fclose(f); + return false; + } + + characters_unarranged = temp; } characters_unarranged[char_count] = new_font_char; @@ -173,6 +238,87 @@ bool load_sprite_font(const char* filename, sprite_font* font) { } } + if (char_count <= 0) { + SDL_Log("Font %s defines no characters!", filename); + + if (characters_unarranged != NULL) { + free(characters_unarranged); + } + fclose(f); + return false; + } + + if (strcmp(sprite_file_name, "") == 0) { + SDL_Log("Font file %s has no spritesheet defined!", + filename + ); + if (characters_unarranged != NULL) { + free(characters_unarranged); + } + + fclose(f); + return false; + } + + char font_dir_name[FILE_NAME_SIZE]; + extract_dir_name(filename, font_dir_name); + + char font_sprite_fname_full[FILE_NAME_SIZE*2]; + snprintf(font_sprite_fname_full, + FILE_NAME_SIZE*2, + "%s/%s", + strcmp(font_dir_name, "") == 0 ? "." : font_dir_name, + sprite_file_name + ); + + SDL_Texture* font_spritesheet = + IMG_LoadTexture(renderer, font_sprite_fname_full); + + if (font_spritesheet == NULL) { + SDL_Log("Failed to load texture %s as spritesheet for font %s!", + font_sprite_fname_full, + filename); + + if (characters_unarranged != NULL) { + free(characters_unarranged); + } + + fclose(f); + return false; + } + + font_char* characters_arranged = + malloc((largest_char-smallest_char+1) * sizeof(font_char)); + + if (characters_arranged == NULL) { + SDL_Log("Failed to allocate space while loading font %s, error %s", + filename, + strerror(errno)); + + if (characters_unarranged != NULL) { + free(characters_unarranged); + } + + SDL_DestroyTexture(font_spritesheet); + fclose(f); + return false; + } + + for (int i = 0; i < char_count; i++) { + font_char* f = &characters_unarranged[i]; + characters_arranged[f->character - smallest_char] = characters_unarranged[i]; + } + + *font = (sprite_font) { + .smallest_character = smallest_char, + .largest_character = largest_char, + .characters = characters_arranged + }; + + strncpy(font->name, font_name, FONT_NAME_SIZE-1); + font_name[FONT_NAME_SIZE-1] = '\0'; + + free(characters_unarranged); fclose(f); return true; } @@ -10,7 +10,7 @@ typedef struct { float width, height; float x_offset, y_offset; float x_advance; - char character; + unsigned char character; } font_char; typedef struct { @@ -20,7 +20,7 @@ typedef struct { font_char* characters; } sprite_font; -bool load_sprite_font(const char* filename, sprite_font* font); +bool load_sprite_font(SDL_Renderer* renderer, const char* filename, sprite_font* font); void free_sprite_font(sprite_font* font); #endif // FONT_H_ |
