mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-08 02:08:22 -10:00
(Widgets) Recompute the derived metrics when a font is rebuilt
7eddfc2 gave the menu drivers this through font_flush(), and noted
that widgets were not covered: they keep their own font struct and
call renderer->flush directly, so they never reach that hook. Same
problem, so the same treatment.
gfx_widget_font_data_t carries the generation the metrics were worked
out at, and gfx_widgets_font_sync() redoes them when it has moved.
The computation is not duplicated to get there - the block that
gfx_widgets_font_init() already ran is what became the sync, so init
and refresh cannot drift apart.
The sync runs before the usage_count check rather than after, so a
widget that drew nothing this frame still lays out correctly on the
next one. Cheap either way: an integer compare when nothing changed.
xmb is still not covered, and its exposure is narrower than it looked
- it caches wideglyph_width and nothing else derived from the face, so
a rebuild leaves word wrapping stale rather than the whole layout. It
holds raw font_data_t pointers and has no impl struct to hang a
generation off, which is why it is left for its own change.
Also fixes samples/gfx/gfx_widgets_sanitize, which this broke:
gfx_widgets.c now calls font_driver_get_generation() and the sample
stubs the font driver out. Stubbed to a constant, since the fonts
there never change underneath. Sample passes again - 392 pushes, 310
frames, clean.
This commit is contained in:
1 parent
8bc46ff400
commit
41bcd2aa7b
3 files changed
+42
-3
No files matched your search
+31
-3
@@ -843,7 +843,16 @@ void gfx_widgets_flush_text(
|
||||
{
|
||||
/* Flushing is slow - only do it if font
|
||||
* has actually been used */
|
||||
if (!font_data || (font_data->usage_count == 0))
|
||||
if (!font_data)
|
||||
return;
|
||||
|
||||
/* A rebuilt font has different metrics; pick them up before
|
||||
* anything is drawn with the old ones. Done here rather than only
|
||||
* when there is something to flush, so a widget that drew nothing
|
||||
* this frame still lays out correctly on the next. */
|
||||
gfx_widgets_font_sync(font_data);
|
||||
|
||||
if (font_data->usage_count == 0)
|
||||
return;
|
||||
|
||||
if (font_data->font && font_data->font->renderer && font_data->font->renderer->flush)
|
||||
@@ -950,6 +959,27 @@ static void gfx_widgets_font_init(
|
||||
* no implicit font to fall back on any more, so the approximate
|
||||
* glyph width set above has to stand on its own. */
|
||||
if (font_data->font)
|
||||
gfx_widgets_font_sync(font_data);
|
||||
|
||||
font_data->usage_count = 0;
|
||||
}
|
||||
|
||||
/* Recompute the derived metrics if the font has been rebuilt since
|
||||
* they were last worked out. Cheap when nothing has changed. The menu
|
||||
* drivers get this from font_flush() via font_driver_sync_impl(), but
|
||||
* widgets keep their own font struct and flush directly. */
|
||||
void gfx_widgets_font_sync(gfx_widget_font_data_t *font_data)
|
||||
{
|
||||
int glyph_width;
|
||||
uint32_t gen = font_driver_get_generation();
|
||||
|
||||
if (!font_data || !font_data->font)
|
||||
return;
|
||||
if (font_data->metrics_generation == gen)
|
||||
return;
|
||||
|
||||
font_data->metrics_generation = gen;
|
||||
|
||||
{
|
||||
glyph_width = font_driver_get_message_width(
|
||||
font_data->font, "a", 1, 1.0f);
|
||||
@@ -962,8 +992,6 @@ static void gfx_widgets_font_init(
|
||||
font_data->line_centre_offset = roundf((font_data->font->metrics.ascender
|
||||
- font_data->font->metrics.descender) * 0.5f);
|
||||
}
|
||||
|
||||
font_data->usage_count = 0;
|
||||
}
|
||||
|
||||
static void gfx_widgets_layout(
|
||||
|
||||
@@ -152,8 +152,14 @@ typedef struct
|
||||
float line_ascender;
|
||||
float line_descender;
|
||||
float line_centre_offset;
|
||||
/* font_driver generation the values above were computed at. A font
|
||||
* rebuilt underneath - a language switch picks a different face -
|
||||
* moves the generation and they are worked out again. */
|
||||
uint32_t metrics_generation;
|
||||
} gfx_widget_font_data_t;
|
||||
|
||||
void gfx_widgets_font_sync(gfx_widget_font_data_t *font_data);
|
||||
|
||||
/* Font data */
|
||||
typedef struct
|
||||
{
|
||||
|
||||
@@ -97,6 +97,11 @@ int font_driver_get_message_width(void *font_data, const char *msg,
|
||||
return (int)(len * 10 * (scale > 0.0f ? scale : 1.0f));
|
||||
}
|
||||
|
||||
/* Bumped by the real font_driver when a font is freed or rebuilt;
|
||||
* gfx_widgets_font_sync() watches it. Constant here: the stub fonts
|
||||
* never change underneath. */
|
||||
uint32_t font_driver_get_generation(void) { return 1; }
|
||||
|
||||
void font_driver_bind_block(void *font_data, void *block)
|
||||
{ (void)font_data; (void)block; }
|
||||
void font_driver_free(font_data_t *font) { (void)font; }
|
||||
|
||||
Reference in new issue
Block a user