Starting work to support <dir prefix=...> in fonts.conf

FontConfig fonts.conf's <dir> tags support a few different
"prefix" attributes.  We'll need to support "xdg" (done here)
and "relative" (forthcoming).
This commit is contained in:
Bill Kendrick 2025-02-22 12:52:27 -08:00
parent 8499dc57c5
commit e04bfc651a
2 changed files with 62 additions and 10 deletions

View file

@ -35,7 +35,6 @@ https://tuxpaint.org/
entries found in system-wide and user-level FontConfig config files. entries found in system-wide and user-level FontConfig config files.
This allows more fonts, and user-specific fonts, to be found & loaded. This allows more fonts, and user-specific fonts, to be found & loaded.
- It looks for: - It looks for:
- FIXME: <system fonts.conf> (Windows)
- `./etc/fonts/fonts.conf` (ships with Tux Paint) (Windows) - `./etc/fonts/fonts.conf` (ships with Tux Paint) (Windows)
- `$FONTCONFIG_PATH/fonts.conf` (macOS/iOS, Linux/Unix) - `$FONTCONFIG_PATH/fonts.conf` (macOS/iOS, Linux/Unix)
- or `/etc/fonts/fonts.conf` (Linux/Unix) - or `/etc/fonts/fonts.conf` (Linux/Unix)
@ -45,7 +44,7 @@ https://tuxpaint.org/
- FIXME: ??? (ships with Tux Paint) (macOS) - FIXME: ??? (ships with Tux Paint) (macOS)
- Note: This adds a build dependency on `libxml-2.0`. - Note: This adds a build dependency on `libxml-2.0`.
Bill Kendrick <bill@newbreedsoftware.com> Bill Kendrick <bill@newbreedsoftware.com>
h/t Mark Kim & Luc Schrijvers h/t Mark Kim, Luc Schrijvers, & Shin-ichi TOYAMA
+ Tux Paint on Windows loads user fonts. + Tux Paint on Windows loads user fonts.
(from e.g., `C:\Users\<username>\AppData\Local\Microsoft\Windows\Fonts`) (from e.g., `C:\Users\<username>\AppData\Local\Microsoft\Windows\Fonts`)

View file

@ -52,6 +52,15 @@
#endif #endif
/* Enums representing the "prefix" attributes Tux Paint understands
in "fonts.conf" `<dir>` tags */
enum {
FC_PREFIX_NONE, /* if none, "default", or "cwd" */
FC_PREFIX_XDG, /* if "xdg", use $XDG_DATA_HOME */
FC_PREFIX_RELATIVE, /* if "relative", relative to the "fonts.conf" where the `<dir>` tag exists */
};
/* /*
The following section renames global variables defined in SDL2_Pango.h to avoid errors during linking. The following section renames global variables defined in SDL2_Pango.h to avoid errors during linking.
It is okay to rename these variables because they are constants. It is okay to rename these variables because they are constants.
@ -998,8 +1007,6 @@ static void loadfonts(SDL_Surface *screen, SDL_Texture *texture, SDL_Renderer *r
} }
#define NUM_FONTCONFIG_CONFIG_PATHS 2 /* system-wide, and local/homedir */
/** /**
* Attempts to allocate space for a char * array to hold * Attempts to allocate space for a char * array to hold
* a set of fontconfig config file paths for load_user_fonts() to * a set of fontconfig config file paths for load_user_fonts() to
@ -1222,12 +1229,23 @@ char * * malloc_fontconfig_config_paths(int num_to_malloc, int * num_actually_ma
{ {
if (xmlStrcmp(cur->name, (const xmlChar *) "dir") == 0) if (xmlStrcmp(cur->name, (const xmlChar *) "dir") == 0)
{ {
xmlChar * path; xmlChar * path, * prefix;
char * path_str; char * path_str;
char prefix_path[1024];
int fontconfig_prefix = FC_PREFIX_NONE;
/* FIXME: We do not currently understand "<dir prefix=...>" -bjk 2025.02.22 /* Check for a "<dir prefix...>" attribute
(prefix may be one of "cwd"/"default", "xdg", or "relative"; (see https://www.freedesktop.org/software/fontconfig/fontconfig-user.html) */
see https://www.freedesktop.org/software/fontconfig/fontconfig-user.html */ prefix = xmlGetProp(cur, (const xmlChar *) "prefix");
if (prefix != NULL)
{
if (xmlStrcmp(prefix, (const xmlChar *) "xdg") == 0)
fontconfig_prefix = FC_PREFIX_XDG;
else if (xmlStrcmp(prefix, (const xmlChar *) "relative") == 0)
fontconfig_prefix = FC_PREFIX_RELATIVE;
xmlFree(prefix);
}
/* Note: As we already look for both system and user fonts on Windows, /* Note: As we already look for both system and user fonts on Windows,
we'll just ignore "WINDOWSUSERFONTDIR" and "WINDOWSFONTDIR" magic paths; we'll just ignore "WINDOWSUSERFONTDIR" and "WINDOWSFONTDIR" magic paths;
@ -1235,7 +1253,6 @@ char * * malloc_fontconfig_config_paths(int num_to_malloc, int * num_actually_ma
See https://gitlab.freedesktop.org/fontconfig/fontconfig/-/blob/main/src/fcxml.c */ See https://gitlab.freedesktop.org/fontconfig/fontconfig/-/blob/main/src/fcxml.c */
path = xmlNodeGetContent(cur); path = xmlNodeGetContent(cur);
if (path != NULL) if (path != NULL)
{ {
path_str = strdup((char *) path /* FIXME: is this cast safe? -bjk 2024.12.29 */); path_str = strdup((char *) path /* FIXME: is this cast safe? -bjk 2024.12.29 */);
@ -1260,6 +1277,42 @@ char * * malloc_fontconfig_config_paths(int num_to_malloc, int * num_actually_ma
#endif #endif
#endif #endif
/* Apply any "prefix" attribute of the <dir> tag: */
prefix_path[0] = '\0';
if (fontconfig_prefix == FC_PREFIX_XDG)
{
/* FIXME: Use xdg function */
if (getenv("XDG_DATA_HOME") != NULL)
{
snprintf(prefix_path, sizeof(prefix_path), "%s/", getenv("XDG_DATA_HOME"));
}
else if (getenv("HOME") != NULL)
{
snprintf(prefix_path, sizeof(prefix_path), "%s/.local/share/", getenv("HOME"));
}
}
else if (fontconfig_prefix == FC_PREFIX_RELATIVE)
{
/* FIXME */
printf("fonts.conf <dir prefix=\"relative\"> not supported yet!\n");
}
if (prefix_path[0] != '\0')
{
char * tmp_str;
size_t len;
len = strlen(path_str) + strlen(prefix_path);
tmp_str = (char *) malloc(sizeof(char *) * (len + 1));
if (tmp_str != NULL)
{
snprintf(tmp_str, len, "%s%s", prefix_path, path_str);
free(path_str);
path_str = tmp_str;
}
}
/* Try to load fonts from the location found in the fonts.conf's <dir> tag */ /* Try to load fonts from the location found in the fonts.conf's <dir> tag */
loadfonts(screen, texture, renderer, (char *) path_str); loadfonts(screen, texture, renderer, (char *) path_str);
free(path_str); free(path_str);