summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/font.c180
-rw-r--r--src/font.h4
2 files changed, 165 insertions, 19 deletions
diff --git a/src/font.c b/src/font.c
index 999c3da..85f7498 100644
--- a/src/font.c
+++ b/src/font.c
@@ -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;
}
diff --git a/src/font.h b/src/font.h
index a26c332..199d65e 100644
--- a/src/font.h
+++ b/src/font.h
@@ -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_