(Font) Stop the font renderers touching the filesystem

Follow-up to 76f8821, which moved the reads and the path lookups up
into font_renderer_create_default(). Two things were left behind.

First, the renderers still decided what to do by looking at the path.
stb branched on

    if (!font_path || !*font_path)

to choose its built-in glyphs, and freetype used the same test to pick
the WiiU shared font. Neither reads a file any more, so the path says
nothing about whether a font actually arrived - font_data does. Branch
on that instead. stb no longer looks at font_path at all and gains a
fallback it did not have: a path that exists but cannot be read now
yields the built-in glyphs rather than failing outright, because the
decision is made on what turned up rather than on what was asked for.

freetype's fontconfig test keeps the path, and should: "fallback" is a
property of the font that was requested, not of whether a file was
found. Only the !*font_path half becomes a byte check.

That also exposed a leak. When fontconfig takes over - because nothing
was read, or because a fallback font was asked for - it supplies its
own bytes, and whatever font_renderer_create_default() had already
read was neither stored nor released. At 2.5 MB for a typical asset
font that is worth having back. Ownership passes to the renderer on
that path too, so it frees them.

Second, file/file_path.h was still included by all three renderers and
used by none - the only remaining mention was in a comment. stb also
kept streams/file_stream.h after its last read went away. Remove them.
The point is not the include lines: while those headers are present
the renderers are still nominally bound to the filesystem, and a path
lookup can creep back in without anyone noticing. Now it would not
compile.

streams/file_stream.h stays in freetype for the one read left, in the
fontconfig branch. Removing that one needs an interface change rather
than a hoist: fontconfig resolves a face index as well as a path
(FC_INDEX, which matters for TrueType collections - CJK system fonts
in particular), and it resolves against the requested font and the
user's locale, so a static candidate list cannot answer it. It means
threading a requested path into the resolver and a face index back out
to init().

stb, freetype and font_driver compile clean under
-Wdeclaration-after-statement. The CoreText change and both WiiU
branches are unbuildable here; all three are mechanical.
This commit is contained in:
O authored and libretroadmin committed 2026-08-08 18:30:30 +02:00
1 parent 9673ceb088
commit 266285f2f7
3 files changed
+24 -15

No files matched your search

-1
View File
@@ -32,7 +32,6 @@
#include <ApplicationServices/ApplicationServices.h>
#endif
#include <file/file_path.h>
#include "../font_driver.h"
+14 -5
View File
@@ -22,7 +22,6 @@
#include <ft2build.h>
#include <file/file_path.h>
#include <streams/file_stream.h>
#include <retro_miscellaneous.h>
#include <string/stdstring.h>
@@ -406,7 +405,8 @@ static void *font_renderer_ft_init(const char *font_path,
goto error;
#ifdef WIIU
if (!*font_path)
/* No bytes arrived, so use the OS shared font. */
if (!font_data_in)
{
void* font_data = NULL;
uint32_t font_data_size = 0;
@@ -421,9 +421,18 @@ static void *font_renderer_ft_init(const char *font_path,
}
else
#elif defined(HAVE_FONTCONFIG_SUPPORT)
/* if fallback font is requested, instead of loading it, we find the full font in the system */
if (!*font_path || strstr(font_path, "fallback"))
/* If no bytes arrived, or a fallback font was asked for, look the
* real font up in the system instead. The path is consulted here
* because "fallback" is a property of what was requested, not of
* whether a file was found. */
if (!font_data_in || (font_path && strstr(font_path, "fallback")))
{
/* fontconfig supplies its own bytes, so release anything the
* caller read for us rather than holding it for the lifetime of
* the font. Ownership passed to us either way. */
free(font_data_in);
font_data_in = NULL;
FcValue locale_boxed;
uint8_t* font_data = NULL;
int64_t font_data_size = 0;
@@ -602,7 +611,7 @@ static const char * const *font_renderer_ft_get_default_fonts(void)
return none;
#else
/* Selection happens in font_renderer_create_default(), which is
* what keeps path_is_valid() out of this file. */
* what keeps path lookups out of this file. */
return font_paths;
#endif
}
+10 -9
View File
@@ -20,8 +20,6 @@
#include <math.h>
#include <stdint.h>
#include <file/file_path.h>
#include <streams/file_stream.h>
#include <string/stdstring.h>
#include <retro_miscellaneous.h>
@@ -1644,6 +1642,9 @@ static void *font_renderer_stb_init(const char *font_path,
stb_font_renderer_t *self =
(stb_font_renderer_t*)calloc(1, sizeof(*self));
/* font_path is unused: what matters is whether bytes arrived. */
(void)font_path;
if (!self || font_size < 1.0f)
goto error;
@@ -1652,7 +1653,7 @@ static void *font_renderer_stb_init(const char *font_path,
font_size = -font_size;
#ifdef WIIU
if (!*font_path)
if (!font_data)
{
uint32_t size = 0;
/* OS-owned shared memory: borrowed, not owned - must not be freed. */
@@ -1663,19 +1664,19 @@ static void *font_renderer_stb_init(const char *font_path,
}
else
#endif
if (!font_path || !*font_path)
if (!font_data || !font_data_len)
{
/* No TrueType font was found; use the built-in glyphs. */
/* Nothing was loaded for us - either no candidate existed or it
* could not be read - so fall back to the built-in glyphs. The
* path is not consulted: this renderer does no file I/O, so the
* bytes are the only thing that says whether a font arrived. */
if (!font_renderer_stb_init_builtin(self, -font_size))
goto error;
return self;
}
else
{
/* Bytes come from font_renderer_create_default(); this renderer
* does no file I/O. Ownership transfers on success. */
if (!font_data || !font_data_len)
goto error;
/* Ownership transfers on success. */
self->font_data = font_data;
self->font_data_size = font_data_len;
self->font_data_owned = true;