Skip to content

Commit

Permalink
switch/application : shared font workaround v2
Browse files Browse the repository at this point in the history
- utilize the use of plGetSharedFont(), leaving possibility to utilize HOS native fallback order

- adjusted fallback chain, now identical with HOS
  • Loading branch information
CaiMiao committed Aug 12, 2022
1 parent 51bbecc commit ff1cc86
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 101 deletions.
12 changes: 6 additions & 6 deletions library/include/borealis/core/font.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ namespace brls
static constexpr const int FONT_INVALID = -1;

static const std::string FONT_REGULAR = "regular"; // regular font (Borealis default font)
static const std::string FONT_STANDARD_REGULAR = "standard"; // regular Standard (Latin/Japanese) font
static const std::string FONT_SCHINESE_REGULAR = "schinese"; // regular S.Chinese font
static const std::string FONT_SCHINESE_EXTEND = "extschinese"; // extended S.Chinese font
static const std::string FONT_TCHINESE_REGULAR = "tchinese"; // regular T.Chinese font
static const std::string FONT_KOREAN_REGULAR = "korean"; // regular Korean font
static const std::string FONT_HOS_STANDARD = "switch_standard"; // Switch Standard (Latin/Japanese) shared font
static const std::string FONT_HOS_SCHINESE = "switch_schinese"; // Switch S.Chinese shared font
static const std::string FONT_HOS_SCHINESE_EXTEND = "switch_extschinese"; // Switch extended S.Chinese shared font
static const std::string FONT_HOS_TCHINESE = "switch_tchinese"; // Switch T.Chinese shared font
static const std::string FONT_HOS_KOREAN = "switch_korean"; // Switch Korean shared font
static const std::string FONT_MATERIAL_ICONS = "material"; // Material icons font
static const std::string FONT_SWITCH_ICONS = "switch"; // Switch icons font (see the HOS shared symbols font for an example)
static const std::string FONT_SWITCH_ICONS = "switch_icons"; // Switch icons font (see the HOS shared symbols font for an example)

typedef std::unordered_map<std::string, int> FontStash;

Expand Down
95 changes: 55 additions & 40 deletions library/lib/core/application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,61 +124,76 @@ void Application::createWindow(std::string windowTitle)
// when defined font stash exists, determine regular font and try to build fallback chain, all fallback failures won't be logged
if (regular == FONT_INVALID)
{
Logger::info("No regular font loaded, checking the rest of font stash");
std::string regularRedir = "";
int standard = Application::getFont(FONT_STANDARD_REGULAR);
int schinese = Application::getFont(FONT_SCHINESE_REGULAR);
int tchinese = Application::getFont(FONT_TCHINESE_REGULAR);
int korean = Application::getFont(FONT_KOREAN_REGULAR);

if (standard != FONT_INVALID)
Logger::info("No borealis regular font loaded, checking the rest of font stash");
int switchIcons = Application::getFont(FONT_SWITCH_ICONS);
if (!switchIcons)
Logger::warning("Switch icons font was not loaded, icons will not be displayed");

std::string fallbackBase = "";
int standard = Application::getFont(FONT_HOS_STANDARD);
int extschinese = Application::getFont(FONT_HOS_SCHINESE_EXTEND);
int schinese = Application::getFont(FONT_HOS_SCHINESE_EXTEND);
int tchinese = Application::getFont(FONT_HOS_TCHINESE);
int korean = Application::getFont(FONT_HOS_KOREAN);

// build-once fallback chain - also check against locale to avoid another bunch of `if`
if ( fallbackBase == "" && extschinese != FONT_INVALID && (locale == LOCALE_ZH_CN || locale == LOCALE_ZH_HANS) )
{
Application::addFontFallback(FONT_STANDARD_REGULAR, FONT_SCHINESE_REGULAR);
Application::addFontFallback(FONT_STANDARD_REGULAR, FONT_SCHINESE_EXTEND);
Application::addFontFallback(FONT_STANDARD_REGULAR, FONT_TCHINESE_REGULAR);
Application::addFontFallback(FONT_STANDARD_REGULAR, FONT_KOREAN_REGULAR);
regularRedir = FONT_STANDARD_REGULAR;
fallbackBase = LOCALE_ZH_HANS;
Application::addFontFallback(FONT_SWITCH_ICONS, FONT_HOS_SCHINESE_EXTEND);
Application::addFontFallback(FONT_SWITCH_ICONS, FONT_HOS_SCHINESE);
Application::addFontFallback(FONT_SWITCH_ICONS, FONT_HOS_TCHINESE);
Application::addFontFallback(FONT_SWITCH_ICONS, FONT_HOS_KOREAN);
Application::addFontFallback(FONT_SWITCH_ICONS, FONT_HOS_STANDARD);
}
// also check against locale to avoid another bunch of `if`
if ( schinese != FONT_INVALID && (locale == LOCALE_ZH_CN || locale == LOCALE_ZH_HANS) )
// fail-safe chain of S.Chinese
if ( fallbackBase == "" && schinese != FONT_INVALID && (locale == LOCALE_ZH_CN || locale == LOCALE_ZH_HANS) )
{
Application::addFontFallback(FONT_SCHINESE_REGULAR, FONT_SCHINESE_EXTEND);
Application::addFontFallback(FONT_SCHINESE_REGULAR, FONT_TCHINESE_REGULAR);
Application::addFontFallback(FONT_SCHINESE_REGULAR, FONT_STANDARD_REGULAR);
Application::addFontFallback(FONT_SCHINESE_REGULAR, FONT_KOREAN_REGULAR);
regularRedir = FONT_SCHINESE_REGULAR;
fallbackBase = LOCALE_ZH_HANS;
Application::addFontFallback(FONT_SWITCH_ICONS, FONT_HOS_SCHINESE);
Application::addFontFallback(FONT_SWITCH_ICONS, FONT_HOS_SCHINESE_EXTEND);
Application::addFontFallback(FONT_SWITCH_ICONS, FONT_HOS_TCHINESE);
Application::addFontFallback(FONT_SWITCH_ICONS, FONT_HOS_KOREAN);
Application::addFontFallback(FONT_SWITCH_ICONS, FONT_HOS_STANDARD);
}
if ( tchinese != FONT_INVALID && (locale == LOCALE_ZH_TW || locale == LOCALE_ZH_HANT) )
if ( fallbackBase == "" && tchinese != FONT_INVALID && (locale == LOCALE_ZH_TW || locale == LOCALE_ZH_HANT) )
{
Application::addFontFallback(FONT_TCHINESE_REGULAR, FONT_SCHINESE_REGULAR);
Application::addFontFallback(FONT_TCHINESE_REGULAR, FONT_SCHINESE_EXTEND);
Application::addFontFallback(FONT_TCHINESE_REGULAR, FONT_STANDARD_REGULAR);
Application::addFontFallback(FONT_TCHINESE_REGULAR, FONT_KOREAN_REGULAR);
regularRedir = FONT_TCHINESE_REGULAR;
fallbackBase = LOCALE_ZH_HANT;
Application::addFontFallback(FONT_SWITCH_ICONS, FONT_HOS_TCHINESE);
Application::addFontFallback(FONT_SWITCH_ICONS, FONT_HOS_SCHINESE_EXTEND);
Application::addFontFallback(FONT_SWITCH_ICONS, FONT_HOS_SCHINESE);
Application::addFontFallback(FONT_SWITCH_ICONS, FONT_HOS_KOREAN);
Application::addFontFallback(FONT_SWITCH_ICONS, FONT_HOS_STANDARD);
}
if ( korean != FONT_INVALID && locale == LOCALE_KO )
if (fallbackBase == "" && korean != FONT_INVALID && locale == LOCALE_KO)
{
Application::addFontFallback(FONT_KOREAN_REGULAR, FONT_STANDARD_REGULAR);
Application::addFontFallback(FONT_KOREAN_REGULAR, FONT_SCHINESE_REGULAR);
Application::addFontFallback(FONT_KOREAN_REGULAR, FONT_SCHINESE_EXTEND);
Application::addFontFallback(FONT_KOREAN_REGULAR, FONT_TCHINESE_REGULAR);
regularRedir = FONT_KOREAN_REGULAR;
fallbackBase = LOCALE_KO;
Application::addFontFallback(FONT_SWITCH_ICONS, FONT_HOS_KOREAN);
Application::addFontFallback(FONT_SWITCH_ICONS, FONT_HOS_SCHINESE);
Application::addFontFallback(FONT_SWITCH_ICONS, FONT_HOS_SCHINESE_EXTEND);
Application::addFontFallback(FONT_SWITCH_ICONS, FONT_HOS_TCHINESE);
Application::addFontFallback(FONT_SWITCH_ICONS, FONT_HOS_STANDARD);
}
if (regularRedir != "")
//
if (fallbackBase == "" && standard != FONT_INVALID)
{
Logger::info("Using {:s} as regular font", regularRedir);
Application::fontStash[FONT_REGULAR] = Application::getFont(regularRedir);
fallbackBase = FONT_HOS_STANDARD;
Application::addFontFallback(FONT_SWITCH_ICONS, FONT_HOS_STANDARD);
Application::addFontFallback(FONT_SWITCH_ICONS, FONT_HOS_SCHINESE_EXTEND);
Application::addFontFallback(FONT_SWITCH_ICONS, FONT_HOS_SCHINESE);
Application::addFontFallback(FONT_SWITCH_ICONS, FONT_HOS_TCHINESE);
Application::addFontFallback(FONT_SWITCH_ICONS, FONT_HOS_KOREAN);
}
if (fallbackBase != "")
{
Logger::info("Built fallback chain for {:s}", fallbackBase);
Application::fontStash[FONT_REGULAR] = Application::getFont(FONT_SWITCH_ICONS);
regular = Application::getFont(FONT_REGULAR); // refresh for next check
}
}

if (regular != FONT_INVALID)
{
// Switch icons
bool switchIcons = Application::addFontFallback(FONT_REGULAR, FONT_SWITCH_ICONS);
if (!switchIcons)
Logger::warning("Switch icons font was not loaded, icons will not be displayed");

// Material icons
bool materialIcons = Application::addFontFallback(FONT_REGULAR, FONT_MATERIAL_ICONS);
if (!materialIcons)
Expand Down
126 changes: 71 additions & 55 deletions library/lib/platforms/switch/switch_font.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,73 +27,89 @@ namespace brls

void SwitchFontLoader::loadFonts()
{
PlFontData font;
Result rc;

// Standard
rc = plGetSharedFontByType(&font, PlSharedFontType_Standard);
PlFontData fonts[PlSharedFontType_Total];
PlFontData* fontsSorted[PlSharedFontType_Total];
std::string locale = Application::getLocale();

bool useStandardOnly = false;
// Compile-time flag
#ifdef SW_STANDARD_FONT_ONLY
bool useStandardOnly = true;
Logger::warning("switch: saving RAM: use standard shared font only!");
#endif

// todo: plGetSharedFont must use (u64)languageCode, conflict with suggested use of (std::string)locale
uint64_t languageCode = 0;
rc = setGetSystemLanguage(&languageCode);
if (R_SUCCEEDED(rc))
Application::loadFontFromMemory(FONT_STANDARD_REGULAR, font.address, font.size, false);
else
Logger::error("switch: could not load Standard shared font: {:#x}", rc);

{
// Detect if non applet
bool isFullFallback = false;
AppletType at = appletGetAppletType();
if (at == AppletType_Application || at == AppletType_SystemApplication) // title takeover
{
isFullFallback = true;
Logger::info("switch: non applet mode, all shared font will be loaded!");
} else {
Logger::info("switch: applet mode, only shared font for current locale will be loaded!");
}
std::string locale = Application::getLocale();

if (locale == LOCALE_ZH_CN || locale == LOCALE_ZH_HANS || isFullFallback)
int total_fonts=0;
rc = plGetSharedFont(languageCode, fonts, PlSharedFontType_Total, &total_fonts);
if (R_SUCCEEDED(rc))
{
// S.Chinese
rc = plGetSharedFontByType(&font, PlSharedFontType_ChineseSimplified);
if (R_SUCCEEDED(rc))
Application::loadFontFromMemory(FONT_SCHINESE_REGULAR, font.address, font.size, false);
else
Logger::error("switch: could not load S.Chinese shared font: {:#x}", rc);

// Ext S.Chinese
rc = plGetSharedFontByType(&font, PlSharedFontType_ExtChineseSimplified);
if (R_SUCCEEDED(rc))
Application::loadFontFromMemory(FONT_SCHINESE_EXTEND, font.address, font.size, false);
else
Logger::error("switch: could not load Ext. S.Chinese shared font: {:#x}", rc);
for (int i=0; i<PlSharedFontType_Total; i++) {
fontsSorted[fonts[i].type] = &fonts[i];
}
}
else
Logger::error("switch: could not load multi shared font: {:#x}", rc);

if (locale == LOCALE_ZH_TW || locale == LOCALE_ZH_HANT || isFullFallback)
{
// T.Chinese
rc = plGetSharedFontByType(&font, PlSharedFontType_ChineseTraditional);
if (R_SUCCEEDED(rc))
Application::loadFontFromMemory(FONT_TCHINESE_REGULAR, font.address, font.size, false);
else
Logger::error("switch: could not load T.Chinese shared font: {:#x}", rc);
}
// Standard
Application::loadFontFromMemory(FONT_HOS_STANDARD,
fontsSorted[PlSharedFontType_Standard]->address,
fontsSorted[PlSharedFontType_Standard]->size, false);

if (locale == LOCALE_KO || isFullFallback)
if (!useStandardOnly)
{
// Korean
rc = plGetSharedFontByType(&font, PlSharedFontType_KO);
if (R_SUCCEEDED(rc))
Application::loadFontFromMemory(FONT_KOREAN_REGULAR, font.address, font.size, false);
bool isFullFallback = false;
// Detect if non applet
AppletType at = appletGetAppletType();
if (at == AppletType_Application || at == AppletType_SystemApplication) // title takeover
isFullFallback = true;

// Compile-time flag
#ifdef SW_DISABLE_FONT_FALLBACK
isFullFallback = false;
Logger::warning("switch: saving RAM: full font fallback is disabled!");
#endif

if (isFullFallback)
Logger::info("switch: non applet mode, all shared fonts will be loaded!");
else
Logger::error("switch: could not load Korean shared font: {:#x}", rc);
Logger::info("switch: applet mode or disabling fallback, only shared font for current locale will be loaded.");

if (locale == LOCALE_ZH_CN || locale == LOCALE_ZH_HANS || isFullFallback)
{
// S.Chinese
Application::loadFontFromMemory(FONT_HOS_SCHINESE,
fontsSorted[PlSharedFontType_ChineseSimplified]->address,
fontsSorted[PlSharedFontType_ChineseSimplified]->size, false);
// Ext S.Chinese
Application::loadFontFromMemory(FONT_HOS_SCHINESE_EXTEND,
fontsSorted[PlSharedFontType_ExtChineseSimplified]->address,
fontsSorted[PlSharedFontType_ExtChineseSimplified]->size, false);
}

if (locale == LOCALE_ZH_TW || locale == LOCALE_ZH_HANT || isFullFallback)
// T.Chinese
Application::loadFontFromMemory(FONT_HOS_TCHINESE,
fontsSorted[PlSharedFontType_ChineseTraditional]->address,
fontsSorted[PlSharedFontType_ChineseTraditional]->size, false);

if (locale == LOCALE_KO || isFullFallback)
// Korean
Application::loadFontFromMemory(FONT_HOS_KOREAN,
fontsSorted[PlSharedFontType_KO]->address,
fontsSorted[PlSharedFontType_KO]->size, false);
}
}
else if (R_FAILED(rc))
Logger::error("switch: shared font loading stopped - could not load languageCode: {:#x}", rc);

// Extented (symbols)
rc = plGetSharedFontByType(&font, PlSharedFontType_NintendoExt);
if (R_SUCCEEDED(rc))
Application::loadFontFromMemory(FONT_SWITCH_ICONS, font.address, font.size, false);
else
Logger::error("switch: could not load Extented shared font: {:#x}", rc);
Application::loadFontFromMemory(FONT_SWITCH_ICONS,
fontsSorted[PlSharedFontType_NintendoExt]->address,
fontsSorted[PlSharedFontType_NintendoExt]->size, false);

// Material icons
if (!this->loadMaterialFromResources())
Expand Down

0 comments on commit ff1cc86

Please sign in to comment.