@ -91,6 +91,8 @@ static float GetGlobalPrescale();
static float GetFixedFontWeight ( ) ;
static void UpdateScale ( ) ;
static void SetStyle ( ImGuiStyle & style , float scale ) ;
static u32 GetTextFontIndex ( ) ;
static u32 GetFixedFontIndex ( ) ;
static bool LoadFontData ( Error * error ) ;
static void ReloadFontDataIfActive ( ) ;
static bool CreateFontAtlas ( Error * error ) ;
@ -118,13 +120,77 @@ static std::optional<ImGuiKey> MapHostKeyEventToImGuiKey(u32 key);
static constexpr float OSD_FADE_IN_TIME = 0.1f ;
static constexpr float OSD_FADE_OUT_TIME = 0.4f ;
static constexpr std : : array < const char * , static_cast < size_t > ( TextFont: : MaxCount ) > TEXT _FONT_NAMES = { {
" Roboto-VariableFont_wdth,wght.ttf " , // Default
" NotoSansSC-VariableFont_wght.ttf " , // Chinese
" NotoSansJP-VariableFont_wght.ttf " , // Japanese
" NotoSansKR-VariableFont_wght.ttf " , // Korean
static constexpr std : : array < const char * , static_cast < size_t > ( LanguageFont: : MaxCount ) > LANGUAGE _FONT_NAMES = { {
nullptr , // Default
" NotoSansSC-VariableFont_wght.ttf " , // Chinese
" NotoSansJP-VariableFont_wght.ttf " , // Japanese
" NotoSansKR-VariableFont_wght.ttf " , // Korean
} } ;
static constexpr const char * FIXED_FONT_NAME = " GoogleSansCode-VariableFont_wght.ttf " ;
# define ENUMERATE_TEXT_FONT_NAMES(X) \
X ( " Roboto " , " Roboto " , " Roboto-VariableFont_wdth,wght.ttf " ) \
X ( " Bitcount " , " Bitcount " , " BitcountPropSingle-VariableFont_CRSV,ELSH,ELXP,slnt,wght.ttf " ) \
X ( " PixelifySans " , " Pixelify Sans " , " PixelifySans-VariableFont_wght.ttf " ) \
X ( " Handjet " , " Handjet " , " Handjet-VariableFont_ELGR,ELSH,wght.ttf " ) \
X ( " Orbitron " , " Orbitron " , " Orbitron-VariableFont_wght.ttf " ) \
X ( " Tektur " , " Tektur " , " Tektur-VariableFont_wdth,wght.ttf " ) \
X ( " PlusJakartaSans " , " Plus Jakarta Sans " , " PlusJakartaSans-VariableFont_wght.ttf " ) \
X ( " Manrope " , " Manrope " , " Manrope-VariableFont_wght.ttf " ) \
X ( " Jersey25 " , " Jersey 25 " , " Jersey25-Regular.ttf " ) \
X ( " VT323 " , " VT323 " , " VT323-Regular.ttf " ) \
X ( " GoogleSansCode " , " Google Sans Code " , " GoogleSansCode-VariableFont_wght.ttf " ) \
X ( " KodeMono " , " Kode Mono " , " KodeMono-VariableFont_wght.ttf " ) \
X ( " RobotoMono " , " Roboto Mono " , " RobotoMono-VariableFont_wght.ttf " )
static constexpr const std : : array TEXT_FONT_NAMES = {
# define ADD_TEXT_FONT(name, display_name, filename) name,
ENUMERATE_TEXT_FONT_NAMES ( ADD_TEXT_FONT )
# undef ADD_TEXT_FONT
} ;
static constexpr const std : : array TEXT_FONT_DISPLAY_NAMES = {
# define ADD_TEXT_FONT(name, display_name, filename) display_name,
ENUMERATE_TEXT_FONT_NAMES ( ADD_TEXT_FONT )
# undef ADD_TEXT_FONT
} ;
static constexpr const std : : array TEXT_FONT_FILENAMES = {
# define ADD_TEXT_FONT(name, display_name, filename) filename,
ENUMERATE_TEXT_FONT_NAMES ( ADD_TEXT_FONT )
# undef ADD_TEXT_FONT
} ;
# undef ENUMERATE_TEXT_FONT_NAMES
static constexpr const char * DEFAULT_TEXT_FONT_NAME = TEXT_FONT_NAMES [ 0 ] ;
# define ENUMERATE_FIXED_FONT_NAMES(X) \
X ( " GoogleSansCode " , " Google Sans Code " , " GoogleSansCode-VariableFont_wght.ttf " ) \
X ( " RobotoMono " , " Roboto Mono " , " RobotoMono-VariableFont_wght.ttf " ) \
X ( " KodeMono " , " Kode Mono " , " KodeMono-VariableFont_wght.ttf " ) \
X ( " Bitcount " , " Bitcount " , " BitcountPropSingle-VariableFont_CRSV,ELSH,ELXP,slnt,wght.ttf " )
static constexpr const std : : array FIXED_FONT_NAMES = {
# define ADD_FIXED_FONT(name, display_name, filename) name,
ENUMERATE_FIXED_FONT_NAMES ( ADD_FIXED_FONT )
# undef ADD_FIXED_FONT
} ;
static constexpr const std : : array FIXED_FONT_DISPLAY_NAMES = {
# define ADD_FIXED_FONT(name, display_name, filename) display_name,
ENUMERATE_FIXED_FONT_NAMES ( ADD_FIXED_FONT )
# undef ADD_FIXED_FONT
} ;
static constexpr const std : : array FIXED_FONT_FILENAMES = {
# define ADD_FIXED_FONT(name, display_name, filename) filename,
ENUMERATE_FIXED_FONT_NAMES ( ADD_FIXED_FONT )
# undef ADD_FIXED_FONT
} ;
# undef ENUMERATE_FIXED_FONT_NAMES
static constexpr const char * DEFAULT_FIXED_FONT_NAME = FIXED_FONT_NAMES [ 0 ] ;
static constexpr const char * FA_FONT_NAME = FONT_ICON_FILE_NAME_FAS ;
static constexpr const char * PF_FONT_NAME = " promptfont.otf " ;
static constexpr const char * EMOJI_FONT_NAME = " TwitterColorEmoji-SVGinOT.ttf " ;
@ -172,9 +238,11 @@ struct ALIGN_TO_CACHE_LINE State
std : : deque < OSDMessage > osd_active_messages ;
float osd_messages_end_y = 0.0f ;
TextFontOrder text_font_order = ImGuiManager : : GetDefaultTextFontOrder ( ) ;
LanguageFontOrder text_font_order = ImGuiManager : : GetLanguageTextFontOrder ( ) ;
u32 text_font_index = 0 ;
u32 fixed_font_index = 0 ;
std : : array < DynamicHeapArray < u8 > , static_cast < size_t > ( TextFont : : MaxCount ) > text_fonts_data ;
std : : array < DynamicHeapArray < u8 > , static_cast < size_t > ( Language Font: : MaxCount ) > text_fonts_data ;
DynamicHeapArray < u8 > fixed_font_data ;
DynamicHeapArray < u8 > icon_fa_font_data ;
DynamicHeapArray < u8 > icon_pf_font_data ;
@ -187,12 +255,12 @@ static State s_state;
} // namespace ImGuiManager
ImGuiManager : : TextFontOrder ImGuiManager : : GetDefault TextFontOrder( )
ImGuiManager : : LanguageFontOrder ImGuiManager : : GetLanguage TextFontOrder( )
{
return { TextFont: : Default , TextFont : : Japanese , TextFont : : Chinese , Text Font: : Korean } ;
return { LanguageFont: : Default , LanguageFont : : Japanese , LanguageFont : : Chinese , Language Font: : Korean } ;
}
void ImGuiManager : : Set TextFontOrder( const Text FontOrder& order )
void ImGuiManager : : Set LanguageFontOrder( const Language FontOrder& order )
{
if ( s_state . text_font_order = = order )
return ;
@ -201,8 +269,105 @@ void ImGuiManager::SetTextFontOrder(const TextFontOrder& order)
ReloadFontDataIfActive ( ) ;
}
std : : span < const char * const > ImGuiManager : : GetTextFontNames ( )
{
return TEXT_FONT_NAMES ;
}
std : : span < const char * const > ImGuiManager : : GetTextFontDisplayNames ( )
{
return TEXT_FONT_DISPLAY_NAMES ;
}
const char * ImGuiManager : : GetDefaultTextFontName ( )
{
return DEFAULT_TEXT_FONT_NAME ;
}
u32 ImGuiManager : : GetTextFontIndex ( )
{
const TinyString name = Core : : GetBaseTinyStringSettingValue ( " Main " , " ImGuiTextFont " , DEFAULT_TEXT_FONT_NAME ) ;
// must be a valid name
const auto it = std : : ranges : : find_if ( TEXT_FONT_NAMES , [ & name ] ( const char * n ) { return ( name = = n ) ; } ) ;
if ( it = = TEXT_FONT_NAMES . end ( ) ) [[unlikely]]
{
ERROR_LOG ( " Invalid text font name: {} " , name ) ;
return 0 ;
}
return static_cast < u32 > ( std : : distance ( TEXT_FONT_NAMES . begin ( ) , it ) ) ;
}
void ImGuiManager : : UpdateTextFont ( )
{
if ( ! IsInitialized ( ) )
return ;
const u32 new_index = GetTextFontIndex ( ) ;
if ( new_index = = s_state . text_font_index )
return ;
s_state . text_font_index = new_index ;
// Force the actual font data to reload.
s_state . text_fonts_data [ static_cast < size_t > ( LanguageFont : : Default ) ] . deallocate ( ) ;
ReloadFontDataIfActive ( ) ;
}
std : : span < const char * const > ImGuiManager : : GetFixedFontNames ( )
{
return FIXED_FONT_NAMES ;
}
std : : span < const char * const > ImGuiManager : : GetFixedFontDisplayNames ( )
{
return FIXED_FONT_DISPLAY_NAMES ;
}
const char * ImGuiManager : : GetDefaultFixedFontName ( )
{
return DEFAULT_FIXED_FONT_NAME ;
}
u32 ImGuiManager : : GetFixedFontIndex ( )
{
const TinyString name = Core : : GetBaseTinyStringSettingValue ( " Main " , " ImGuiFixedFont " , DEFAULT_FIXED_FONT_NAME ) ;
// must be a valid name
const auto it = std : : ranges : : find_if ( FIXED_FONT_NAMES , [ & name ] ( const char * n ) { return ( name = = n ) ; } ) ;
if ( it = = FIXED_FONT_NAMES . end ( ) ) [[unlikely]]
{
ERROR_LOG ( " Invalid fixed font name: {} " , name ) ;
return 0 ;
}
return static_cast < u32 > ( std : : distance ( FIXED_FONT_NAMES . begin ( ) , it ) ) ;
}
void ImGuiManager : : UpdateFixedFont ( )
{
if ( ! IsInitialized ( ) )
return ;
const u32 new_index = GetFixedFontIndex ( ) ;
if ( new_index = = s_state . fixed_font_index )
return ;
s_state . fixed_font_index = new_index ;
// Force the actual font data to reload.
s_state . fixed_font_data . deallocate ( ) ;
ReloadFontDataIfActive ( ) ;
}
bool ImGuiManager : : Initialize ( Error * error )
{
s_state . text_font_index = GetTextFontIndex ( ) ;
s_state . fixed_font_index = GetFixedFontIndex ( ) ;
if ( ! LoadFontData ( error ) )
{
Error : : AddPrefix ( error , " Failed to load font data: " ) ;
@ -696,14 +861,16 @@ bool ImGuiManager::LoadFontData(Error* error)
} ;
// only load used text fonts, that way we don't waste memory on mini
for ( const TextFont text _font : s_state . text_font_order )
for ( const LanguageFont language _font : s_state . text_font_order )
{
const u32 index = static_cast < u32 > ( text _font) ;
const u32 index = static_cast < u32 > ( language _font) ;
if ( ! s_state . text_fonts_data [ index ] . empty ( ) )
continue ;
std : : optional < DynamicHeapArray < u8 > > font_data =
Host : : ReadResourceFile ( font_resource_name ( TEXT_FONT_NAMES [ index ] ) , true , error ) ;
std : : optional < DynamicHeapArray < u8 > > font_data = Host : : ReadResourceFile (
font_resource_name ( ( language_font ! = LanguageFont : : Default ) ? LANGUAGE_FONT_NAMES [ index ] :
TEXT_FONT_FILENAMES [ s_state . text_font_index ] ) ,
true , error ) ;
if ( ! font_data . has_value ( ) )
return false ;
@ -713,7 +880,7 @@ bool ImGuiManager::LoadFontData(Error* error)
if ( s_state . fixed_font_data . empty ( ) )
{
std : : optional < DynamicHeapArray < u8 > > font_data =
Host : : ReadResourceFile ( font_resource_name ( FIXED_FONT_ NAME) , true , error ) ;
Host : : ReadResourceFile ( font_resource_name ( FIXED_FONT_ FILE NAMES[ s_state . fixed_font_index ] ) , true , error ) ;
if ( ! font_data . has_value ( ) )
return false ;
@ -768,8 +935,8 @@ bool ImGuiManager::CreateFontAtlas(Error* error)
// First text font has to be added before the icon fonts.
// Remaining fonts are added after the icon font, otherwise the wrong glyphs will be used in the UI.
const Text Font first_font = s_state . text_font_order . front ( ) ;
StringUtil : : Strlcpy ( text_cfg . Name , TEXT_FONT_NAMES [ static_cast < size_t > ( first_font ) ] , std : : size ( text_cfg . Name ) ) ;
const Language Font first_font = s_state . text_font_order . front ( ) ;
StringUtil : : Strlcpy ( text_cfg . Name , " TextFont " , std : : size ( text_cfg . Name ) ) ;
auto & first_font_data = s_state . text_fonts_data [ static_cast < size_t > ( first_font ) ] ;
Assert ( ! first_font_data . empty ( ) ) ;
s_state . text_font =
@ -823,13 +990,12 @@ bool ImGuiManager::CreateFontAtlas(Error* error)
text_cfg . MergeMode = true ;
for ( size_t i = 1 ; i < s_state . text_font_order . size ( ) ; i + + )
{
const Text Font text_font_idx = s_state . text_font_order [ i ] ;
const Language Font text_font_idx = s_state . text_font_order [ i ] ;
if ( text_font_idx = = first_font )
continue ;
auto & font_data = s_state . text_fonts_data [ static_cast < size_t > ( text_font_idx ) ] ;
Assert ( ! font_data . empty ( ) ) ;
StringUtil : : Strlcpy ( text_cfg . Name , " TextFont- " , std : : size ( text_cfg . Name ) ) ;
if ( ! ImGui : : GetIO ( ) . Fonts - > AddFontFromMemoryTTF ( font_data . data ( ) , static_cast < int > ( font_data . size ( ) ) ,
default_text_size , DEFAULT_TEXT_FONT_WEIGHT , & text_cfg ) )
{
@ -862,16 +1028,12 @@ void ImGuiManager::ReloadFontDataIfActive()
if ( ! s_state . imgui_context )
return ;
ImGui : : EndFrame ( ) ;
Error error ;
if ( ! CreateFontAtlas( & error ) ) [[unlikely]]
if ( ! LoadFontData ( & error ) | | ! CreateFontAtlas ( & error ) ) [[unlikely]]
{
VideoThread : : ReportFatalErrorAndShutdown ( fmt : : format ( " Failed to recreate font atlas: \n {} " , error . GetDescription ( ) ) ) ;
return ;
}
NewFrame ( Timer : : GetCurrentValue ( ) ) ;
}
float ImGuiManager : : GetOSDMessageDuration ( OSDMessageType type )
@ -1322,7 +1484,8 @@ void Host::AddIconOSDMessage(OSDMessageType type, std::string key, const char* i
{
const std : : string_view icon_sv = icon ;
const OSDMessageIconType icon_type = ImGuiManager : : GetOSDMessageIconType ( icon_sv ) ;
ImGuiManager : : AddOSDMessage ( type , std : : move ( key ) , icon_type , std : : string ( icon_sv ) , std : : move ( title ) , std : : move ( message ) ) ;
ImGuiManager : : AddOSDMessage ( type , std : : move ( key ) , icon_type , std : : string ( icon_sv ) , std : : move ( title ) ,
std : : move ( message ) ) ;
}
void Host : : AddIconOSDMessage ( OSDMessageType type , std : : string key , std : : string icon , std : : string title ,