Skip to content

Commit

Permalink
switch/application : shared font workaround v3
Browse files Browse the repository at this point in the history
- utilize HOS native fallback order
- may still dirty but works......
- force push: some cleanup
  • Loading branch information
CaiMiao committed Aug 18, 2022
1 parent 1c90555 commit 57df225
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 115 deletions.
4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE
CFLAGS := -g -Wall -O2 -ffunction-sections \
$(ARCH) $(DEFINES)

CFLAGS += $(INCLUDE) -D__SWITCH__
CFLAGS += $(INCLUDE) -D__SWITCH__ \
# -DSW_STANDARD_FONT_ONLY \
# -DSW_DISABLE_FONT_FALLBACK

CXXFLAGS := $(CFLAGS) -std=c++1z -O2 -Wno-volatile

Expand Down
31 changes: 29 additions & 2 deletions library/include/borealis/core/font.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,45 @@

#include <string>
#include <unordered_map>
#include <vector>

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_MATERIAL_ICONS = "material"; // Material icons font

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

// HOS Shared 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_icons"; // Switch icons font (see the HOS shared symbols font for an example)

typedef std::unordered_map<std::string, int> FontStash;
typedef enum {
HOSSharedFontType_Standard = 0, ///< Japan, US and Europe
HOSSharedFontType_ChineseSimplified = 1, ///< Chinese Simplified
HOSSharedFontType_ExtChineseSimplified = 2, ///< Extended Chinese Simplified
HOSSharedFontType_ChineseTraditional = 3, ///< Chinese Traditional
HOSSharedFontType_KO = 4, ///< Korean (Hangul)
HOSSharedFontType_NintendoExt = 5, ///< Nintendo Extended. This font only has the special Nintendo-specific characters, which aren't available with the other fonts.
HOSSharedFontType_Total, ///< Total fonts supported by this enum.
} HOSSharedFontType;

typedef std::vector<uint32_t> SharedFontFallbackOrder;
static std::unordered_map<int, std::string> HOSSharedFontMap = {
{HOSSharedFontType_Standard, FONT_HOS_STANDARD},
{HOSSharedFontType_ChineseSimplified, FONT_HOS_SCHINESE},
{HOSSharedFontType_ExtChineseSimplified, FONT_HOS_SCHINESE_EXTEND},
{HOSSharedFontType_ChineseTraditional, FONT_HOS_TCHINESE},
{HOSSharedFontType_KO, FONT_HOS_KOREAN},
{HOSSharedFontType_NintendoExt, FONT_SWITCH_ICONS},
};

// Platform interface to load fonts from disk or other sources (system / shared font...)
class FontLoader
Expand All @@ -48,6 +71,10 @@ class FontLoader
* of the "built-in" fonts defined in the FONT_* constants above.
*/
virtual void loadFonts() = 0;
/**
* Load font fallback order, mainly for SW.
*/
virtual bool loadSharedFontFallbackOrder(SharedFontFallbackOrder* order_list, int order_list_count = HOSSharedFontType_Total);

protected:
/**
Expand Down
1 change: 1 addition & 0 deletions library/include/borealis/platforms/switch/switch_font.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class SwitchFontLoader : public FontLoader
{
public:
void loadFonts() override;
bool loadSharedFontFallbackOrder(SharedFontFallbackOrder* order_list, int order_list_count = HOSSharedFontType_Total) override;
};

} // namespace brls
90 changes: 26 additions & 64 deletions library/lib/core/application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,79 +121,41 @@ void Application::createWindow(std::string windowTitle)
std::string locale = Application::getLocale();
int regular = Application::getFont(FONT_REGULAR);

// 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)
// switch only: when defined font stash exists, try to find available font stash,
// build fallback chain and switch regular font, all fallback failures won't be logged
if (Application::platform->getName() == "Switch" && regular == 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) )
{
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);
}
// fail-safe chain of S.Chinese
if ( fallbackBase == "" && schinese != FONT_INVALID && (locale == LOCALE_ZH_CN || locale == LOCALE_ZH_HANS) )
{
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 ( fallbackBase == "" && tchinese != FONT_INVALID && (locale == LOCALE_ZH_TW || locale == LOCALE_ZH_HANT) )
{
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 (fallbackBase == "" && korean != FONT_INVALID && locale == LOCALE_KO)
{
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 (fallbackBase == "" && standard != FONT_INVALID)
Logger::info("switch: no borealis regular font loaded, checking the rest of font stash");

// get fallback order
SharedFontFallbackOrder fallbackOrder {};
Application::platform->getFontLoader()->loadSharedFontFallbackOrder(&fallbackOrder); // orderCount == HOSSharedFontType_Total

// determine first available font stash as regular font
int firstFont = 0;
for (int i=firstFont; regular == FONT_INVALID && i<HOSSharedFontType_Total; i++)
{
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);
firstFont = i;
regular = Application::getFont(HOSSharedFontMap[fallbackOrder.at(firstFont)]);
}
if (fallbackBase != "")
if (regular != FONT_INVALID)
{
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
Logger::debug("regular font switched to: {:s}", HOSSharedFontMap[fallbackOrder.at(firstFont)]);
// build fallback chain to regular font (switch icons)
for (int i=firstFont+1; i<HOSSharedFontType_Total; i++)
Application::addFontFallback(HOSSharedFontMap[fallbackOrder.at(firstFont)], HOSSharedFontMap[fallbackOrder.at(i)]);

// redirect regular font stash
Application::fontStash[FONT_REGULAR] = regular;
}
}

if (regular != FONT_INVALID)
{
// Switch icons - duplicate
// 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
11 changes: 11 additions & 0 deletions library/lib/core/font.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,15 @@ bool FontLoader::loadMaterialFromResources()
return this->loadFontFromFile(FONT_MATERIAL_ICONS, MATERIAL_ICONS_PATH);
}

bool FontLoader::loadSharedFontFallbackOrder(SharedFontFallbackOrder* order_list, int order_list_count)
{
// stub
Logger::warning("stub loadSharedFontFallbackOrder");
for (int i=0; i<order_list_count; i++)
{
order_list->push_back(i);
}
return true;
}

} // namespace brls
121 changes: 73 additions & 48 deletions library/lib/platforms/switch/switch_font.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,60 +51,60 @@ void SwitchFontLoader::loadFonts()
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);

// Standard
Application::loadFontFromMemory(FONT_HOS_STANDARD,
fontsSorted[PlSharedFontType_Standard]->address,
fontsSorted[PlSharedFontType_Standard]->size, false);
// Standard
Application::loadFontFromMemory(FONT_HOS_STANDARD,
fontsSorted[PlSharedFontType_Standard]->address,
fontsSorted[PlSharedFontType_Standard]->size, false);

if (!useStandardOnly)
{
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::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)
if (!useStandardOnly)
{
// 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);
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::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);
}

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
Logger::error("switch: shared font loading stopped - could not load multi shared font: {:#x}", rc);
}
else if (R_FAILED(rc))
else
Logger::error("switch: shared font loading stopped - could not load languageCode: {:#x}", rc);

Application::loadFontFromMemory(FONT_SWITCH_ICONS,
Expand All @@ -116,4 +116,29 @@ void SwitchFontLoader::loadFonts()
Logger::error("switch: could not load Material icons font from resources", rc);
}

bool SwitchFontLoader::loadSharedFontFallbackOrder(SharedFontFallbackOrder* order_list, int order_list_count)
{
Result rc;
PlFontData fonts[PlSharedFontType_Total];

// 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))
{
int total_fonts=0;
rc = plGetSharedFont(languageCode, fonts, PlSharedFontType_Total, &total_fonts);
if (R_SUCCEEDED(rc))
{
for (int i=0; i<order_list_count; i++)
{
order_list->push_back(fonts[i].type);
Logger::debug("switch: pushing type {:#x} to font fallback order list", order_list->at(i));
}
}
return true;
}
return false;
}

} // namespace brls

0 comments on commit 57df225

Please sign in to comment.