Skip to content

Commit

Permalink
Add font containers for global and custom fonts
Browse files Browse the repository at this point in the history
All global fonts and all custom fonts in a level are now loaded, and
added to their respective "vectors". The selected font is still always
as the global font.png, and the custom level font also isn't selected
yet, but it's now easier to implement that.

Also, I added FILESYSTEM_enumerateAssets, which TerryCavanagh#902 already has but I
needed it now. I also rewrote it to not use std::vector<std::string>
(that was my idea, it's also how FILESYSTEM_getLanguageCodes works,
until the next commit...)
  • Loading branch information
Daaaav committed Jan 16, 2023
1 parent b07fb85 commit b2fadd0
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 11 deletions.
86 changes: 86 additions & 0 deletions desktop_version/src/FileSystemUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1042,6 +1042,92 @@ void FILESYSTEM_enumerateLevelDirFileNames(
}
}

typedef struct _enum_handle
{
char** physfs_list;
char** item;
char* mounted_path;
}
enum_handle;

const char* FILESYSTEM_enumerate(const char* folder, void** p_handle)
{
/* List all files in a folder with PHYSFS_enumerateFiles.
*
* Doing it this way means we can decide and filter what's in the lists (in
* wrapper functions), and the caller does not have to PHYSFS_freeList.
*
* Called like this:
*
* void* handle = NULL;
* const char* item;
* while ((item = FILESYSTEM_enumerate("graphics", &handle)) != NULL)
* {
* puts(item);
* }
*/

enum_handle* handle = (enum_handle*) *p_handle;
if (*p_handle == NULL)
{
/* First iteration, set things up */
handle = (enum_handle*) SDL_malloc(sizeof(enum_handle));
char* mounted_path = (char*) SDL_malloc(MAX_PATH);
if (handle == NULL || mounted_path == NULL)
{
VVV_free(handle);
VVV_free(mounted_path);
return NULL;
}
handle->mounted_path = mounted_path;
getMountedPath(handle->mounted_path, MAX_PATH, folder);
handle->physfs_list = PHYSFS_enumerateFiles(handle->mounted_path);
handle->item = handle->physfs_list;

*p_handle = handle;
}

if (*handle->item == NULL)
{
/* We're done! */
PHYSFS_freeList(handle->physfs_list);
VVV_free(handle->mounted_path);
VVV_free(handle);
return NULL;
}

/* Return the next item, and increment the pointer */
return *(handle->item++);
}

const char* FILESYSTEM_enumerateAssets(const char* folder, void** p_handle)
{
/* This function enumerates ONLY level-specific assets.
* If there are only global assets and no level-specific ones,
* we want an empty list.
*
* This function is called the same way as FILESYSTEM_enumerate, see above. */

if (!FILESYSTEM_isAssetMounted(folder))
{
return NULL;
}

const char* item;
while ((item = FILESYSTEM_enumerate(folder, p_handle)) != NULL)
{
enum_handle* handle = (enum_handle*) *p_handle;
char full_name[128];
SDL_snprintf(full_name, sizeof(full_name), "%s/%s", handle->mounted_path, item);
if (FILESYSTEM_isFile(full_name) && item[0] != '.')
{
return item;
}
}

return NULL;
}

std::vector<std::string> FILESYSTEM_getLanguageCodes(void)
{
std::vector<std::string> list;
Expand Down
3 changes: 3 additions & 0 deletions desktop_version/src/FileSystemUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ bool FILESYSTEM_loadAssetTiXml2Document(const char *name, tinyxml2::XMLDocument&

void FILESYSTEM_enumerateLevelDirFileNames(void (*callback)(const char* filename));

const char* FILESYSTEM_enumerate(const char* folder, void** p_handle);
const char* FILESYSTEM_enumerateAssets(const char* folder, void** p_handle);

std::vector<std::string> FILESYSTEM_getLanguageCodes(void);

bool FILESYSTEM_levelDirHasError(void);
Expand Down
80 changes: 71 additions & 9 deletions desktop_version/src/Font.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "Graphics.h"
#include "Localization.h"
#include "UtilityClass.h"
#include "Vlogging.h"
#include "XMLUtils.h"

// Sigh... This is the second forward-declaration, we need to put this in a header file
Expand All @@ -16,7 +17,14 @@ SDL_Surface* LoadImage(const char *filename);
namespace font
{

Font temp_bfont; // replace with like, a vector of all loaded fonts
static FontContainer fonts_main = {0};
static FontContainer fonts_custom = {0};

static size_t font_idx_interface = 0;
static size_t font_idx_8x8 = 0;

static bool font_idx_custom_is_custom = false;
static size_t font_idx_custom = 0;

static void codepoint_split(
const uint32_t codepoint,
Expand Down Expand Up @@ -130,8 +138,19 @@ static bool decode_xml_range(tinyxml2::XMLElement* elem, unsigned* start, unsign
return true;
}

static void load_font(Font* f, const char* name)
static size_t load_font(FontContainer* container, const char* name)
{
Font* new_fonts = (Font*) SDL_realloc(container->fonts, sizeof(Font)*(container->count+1));
if (new_fonts == NULL)
{
return 0;
}
container->fonts = new_fonts;
size_t f_idx = container->count++;
Font* f = &container->fonts[f_idx];

vlog_info("Loading font \"%s\"...", name);

char name_png[256];
char name_txt[256];
char name_xml[256];
Expand Down Expand Up @@ -171,7 +190,7 @@ static void load_font(Font* f, const char* name)

if (f->image == NULL || f->scratch_1x == NULL || f->scratch_8x == NULL)
{
return;
return f_idx;
}

f->n_x_glyphs = f->image->w / f->glyph_w;
Expand Down Expand Up @@ -293,17 +312,60 @@ static void load_font(Font* f, const char* name)
}
}
}

return f_idx;
}

static void load_font_filename(bool is_custom, const char* filename)
{
/* Load font.png, and everything that matches *.fontmeta (but not font.fontmeta) */
size_t expected_ext_start;
bool is_fontpng = SDL_strcmp(filename, "font.png") == 0;
if (is_fontpng)
{
expected_ext_start = SDL_strlen(filename)-4;
}
else
{
expected_ext_start = SDL_strlen(filename)-9;
}
if (is_fontpng || (endsWith(filename, ".fontmeta") && SDL_strcmp(filename, "font.fontmeta") != 0))
{
char font_name[128];
SDL_strlcpy(font_name, filename, sizeof(font_name));
font_name[SDL_min(127, expected_ext_start)] = '\0';

size_t f_idx = load_font(is_custom ? &fonts_custom : &fonts_main, font_name);

if (is_fontpng && !is_custom)
{
font_idx_8x8 = f_idx;
}
}
}

void load_main(void)
{
// TODO PHYSFS_enumerateFiles, load everything that matches *.fontmeta or font.png (but not font.fontmeta)
load_font(&temp_bfont, "font");
/* Load all global fonts */
void* handle = NULL;
const char* item;
while ((item = FILESYSTEM_enumerate("graphics", &handle)) != NULL)
{
load_font_filename(false, item);
}
}

void load_custom(void)
{
// Custom (level-specific assets) fonts NYI
/* Load all custom (level-specific assets) fonts */
void* handle = NULL;
const char* item;
while ((item = FILESYSTEM_enumerateAssets("graphics", &handle)) != NULL)
{
load_font_filename(true, item);
}

// TODO: decide font_idx_custom
}

void unload_custom(void)
Expand All @@ -315,7 +377,7 @@ void unload_custom(void)
void destroy(void)
{
/* Unload all fonts (main and custom) for exiting */
Font* f = &temp_bfont;
Font* f = &fonts_main.fonts[font_idx_8x8]; // TODO!
VVV_freefunc(SDL_FreeSurface, f->image);

for (int i = 0; i < FONT_N_PAGES; i++)
Expand Down Expand Up @@ -352,7 +414,7 @@ bool next_wrap(
goto next;
}

linewidth += get_advance(&font::temp_bfont, str[idx]);
linewidth += get_advance(&fonts_main.fonts[font_idx_8x8], str[idx]); // TODO get font via argument!

switch (str[idx])
{
Expand Down Expand Up @@ -621,7 +683,7 @@ static Font* fontsel_to_font(int sel)
{
/* Take font selection integer (0-31) and turn it into the correct Font */
// TODO handle all these cases here like 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 etc
return &font::temp_bfont;
return &fonts_main.fonts[font_idx_8x8];
}

#define FLAG_PART(start, count) ((flags >> start) % (1 << count))
Expand Down
8 changes: 6 additions & 2 deletions desktop_version/src/Font.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ struct Font
GlyphInfo* glyph_page[FONT_N_PAGES];
};

struct FontContainer
{
size_t count;
Font* fonts;
};

struct PrintFlags
{
uint8_t scale;
Expand Down Expand Up @@ -103,8 +109,6 @@ struct PrintFlags
#define PR_CJK_LOW (1 << 20) /* larger fonts should stick out fully on the bottom (draw at Y) */
#define PR_CJK_HIGH (2 << 20) /* larger fonts should stick out fully on the top */

extern Font temp_bfont;

void load_main(void);
void load_custom(void);
void unload_custom(void);
Expand Down

0 comments on commit b2fadd0

Please sign in to comment.