mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-06-04 15:05:02 -06:00
Refactor font path handling and remove unused functions
This commit is contained in:
parent
70a5460277
commit
5dde0cc70f
@ -878,10 +878,6 @@ void load(const std::filesystem::path& path, bool is_game_specific) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_game_specific) {
|
|
||||||
system_font_overrides.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.contains("General")) {
|
if (data.contains("General")) {
|
||||||
const toml::value& general = data.at("General");
|
const toml::value& general = data.at("General");
|
||||||
|
|
||||||
|
|||||||
@ -145,7 +145,7 @@ static auto UserPaths = [] {
|
|||||||
notice_file.close();
|
notice_file.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto instructions_path = user_dir / SYSFONTS_DIR / "Instructions.txt";
|
const auto instructions_path = user_dir / FONTS_DIR / "Instructions.txt";
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
if (!std::filesystem::exists(instructions_path, ec)) {
|
if (!std::filesystem::exists(instructions_path, ec)) {
|
||||||
std::ofstream font_instructions(instructions_path);
|
std::ofstream font_instructions(instructions_path);
|
||||||
|
|||||||
@ -65,7 +65,7 @@ void EmulatorSettings::SetInstance(std::shared_ptr<EmulatorSettings> instance) {
|
|||||||
|
|
||||||
std::filesystem::path EmulatorSettings::GetSysFontsDir() {
|
std::filesystem::path EmulatorSettings::GetSysFontsDir() {
|
||||||
if (m_general.sys_fonts_dir.value.empty()) {
|
if (m_general.sys_fonts_dir.value.empty()) {
|
||||||
return Common::FS::GetUserPath(Common::FS::PathType::FontDir);
|
return Common::FS::GetUserPath(Common::FS::PathType::FontsDir);
|
||||||
}
|
}
|
||||||
return m_general.sys_fonts_dir.value;
|
return m_general.sys_fonts_dir.value;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,7 +31,6 @@
|
|||||||
#include FT_TRUETYPE_TABLES_H
|
#include FT_TRUETYPE_TABLES_H
|
||||||
#include "common/config.h"
|
#include "common/config.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/singleton.h"
|
|
||||||
#include "core/file_sys/fs.h"
|
#include "core/file_sys/fs.h"
|
||||||
#include "core/libraries/error_codes.h"
|
#include "core/libraries/error_codes.h"
|
||||||
#include "core/libraries/font/font.h"
|
#include "core/libraries/font/font.h"
|
||||||
@ -549,10 +548,10 @@ static const SystemFontDefinition* FindSystemFontDefinition(u32 font_set_type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static std::filesystem::path GetSysFontBaseDir() {
|
static std::filesystem::path GetSysFontBaseDir() {
|
||||||
std::filesystem::path base = Config::getSysFontPath();
|
std::filesystem::path base = Config::getFontsPath();
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
if (base.empty()) {
|
if (base.empty()) {
|
||||||
LOG_ERROR(Lib_Font, "SystemFonts: SysFontPath not set");
|
LOG_ERROR(Lib_Font, "SystemFonts: FontsPath not set");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
if (std::filesystem::is_directory(base, ec)) {
|
if (std::filesystem::is_directory(base, ec)) {
|
||||||
@ -561,7 +560,7 @@ static std::filesystem::path GetSysFontBaseDir() {
|
|||||||
if (std::filesystem::is_regular_file(base, ec)) {
|
if (std::filesystem::is_regular_file(base, ec)) {
|
||||||
return base.parent_path();
|
return base.parent_path();
|
||||||
}
|
}
|
||||||
LOG_ERROR(Lib_Font, "SystemFonts: SysFontPath '{}' is not a valid directory or file",
|
LOG_ERROR(Lib_Font, "SystemFonts: FontsPath '{}' is not a valid directory or file",
|
||||||
base.string());
|
base.string());
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -604,75 +603,12 @@ static std::filesystem::path ResolveSystemFontPathCandidate(const std::filesyste
|
|||||||
return direct;
|
return direct;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string MacroToCamel(const char* macro_key) {
|
|
||||||
if (!macro_key) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
std::string s(macro_key);
|
|
||||||
const std::string prefix = "FONTSET_";
|
|
||||||
if (s.rfind(prefix, 0) != 0) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
std::string out = "FontSet";
|
|
||||||
size_t pos = prefix.size();
|
|
||||||
while (pos < s.size()) {
|
|
||||||
size_t next = s.find('_', pos);
|
|
||||||
const size_t len = (next == std::string::npos) ? (s.size() - pos) : (next - pos);
|
|
||||||
std::string token = s.substr(pos, len);
|
|
||||||
for (auto& c : token) {
|
|
||||||
c = static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
|
|
||||||
}
|
|
||||||
if (!token.empty()) {
|
|
||||||
token[0] = static_cast<char>(std::toupper(static_cast<unsigned char>(token[0])));
|
|
||||||
}
|
|
||||||
out += token;
|
|
||||||
if (next == std::string::npos) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
pos = next + 1;
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::filesystem::path ResolveSystemFontPath(u32 font_set_type) {
|
static std::filesystem::path ResolveSystemFontPath(u32 font_set_type) {
|
||||||
if (const auto* def = FindSystemFontDefinition(font_set_type); def) {
|
if (const auto* def = FindSystemFontDefinition(font_set_type); def) {
|
||||||
const auto base_dir = GetSysFontBaseDir();
|
const auto base_dir = GetSysFontBaseDir();
|
||||||
if (base_dir.empty()) {
|
if (base_dir.empty()) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
if (auto override_path = Config::getSystemFontOverride(def->config_key)) {
|
|
||||||
if (!override_path->empty() && !override_path->is_absolute() &&
|
|
||||||
!override_path->has_parent_path()) {
|
|
||||||
return ResolveSystemFontPathCandidate(base_dir, *override_path);
|
|
||||||
}
|
|
||||||
LOG_ERROR(Lib_Font,
|
|
||||||
"SystemFonts: override for '{}' must be a filename only (no path): '{}'",
|
|
||||||
def->config_key, override_path->string());
|
|
||||||
}
|
|
||||||
const auto camel_key = MacroToCamel(def->config_key);
|
|
||||||
if (!camel_key.empty()) {
|
|
||||||
if (auto override_path2 = Config::getSystemFontOverride(camel_key)) {
|
|
||||||
if (!override_path2->empty() && !override_path2->is_absolute() &&
|
|
||||||
!override_path2->has_parent_path()) {
|
|
||||||
return ResolveSystemFontPathCandidate(base_dir, *override_path2);
|
|
||||||
}
|
|
||||||
LOG_ERROR(Lib_Font,
|
|
||||||
"SystemFonts: override for '{}' must be a filename only (no path): '{}'",
|
|
||||||
camel_key, override_path2->string());
|
|
||||||
}
|
|
||||||
std::string lower_camel = camel_key;
|
|
||||||
lower_camel[0] =
|
|
||||||
static_cast<char>(std::tolower(static_cast<unsigned char>(lower_camel[0])));
|
|
||||||
if (auto override_path3 = Config::getSystemFontOverride(lower_camel)) {
|
|
||||||
if (!override_path3->empty() && !override_path3->is_absolute() &&
|
|
||||||
!override_path3->has_parent_path()) {
|
|
||||||
return ResolveSystemFontPathCandidate(base_dir, *override_path3);
|
|
||||||
}
|
|
||||||
LOG_ERROR(Lib_Font,
|
|
||||||
"SystemFonts: override for '{}' must be a filename only (no path): '{}'",
|
|
||||||
lower_camel, override_path3->string());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (def->default_file && *def->default_file) {
|
if (def->default_file && *def->default_file) {
|
||||||
return ResolveSystemFontPathCandidate(base_dir, def->default_file);
|
return ResolveSystemFontPathCandidate(base_dir, def->default_file);
|
||||||
}
|
}
|
||||||
@ -4318,11 +4254,7 @@ s32 PS4_SYSV_ABI sceFontOpenFontSet(OrbisFontLib library, u32 fontSetType, u32 o
|
|||||||
return release_library_and_clear_out(ORBIS_FONT_ERROR_NO_SUPPORT_FUNCTION);
|
return release_library_and_clear_out(ORBIS_FONT_ERROR_NO_SUPPORT_FUNCTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::filesystem::path primary_path =
|
std::filesystem::path primary_path = Internal::ResolveSystemFontPath(fontSetType);
|
||||||
Internal::ResolveSystemFontPathFromConfigOnly(fontSetType);
|
|
||||||
if (primary_path.empty()) {
|
|
||||||
primary_path = Internal::ResolveSystemFontPath(fontSetType);
|
|
||||||
}
|
|
||||||
if (primary_path.empty()) {
|
if (primary_path.empty()) {
|
||||||
LOG_ERROR(Lib_Font, "NO_SUPPORT_FONTSET");
|
LOG_ERROR(Lib_Font, "NO_SUPPORT_FONTSET");
|
||||||
return release_library_and_clear_out(ORBIS_FONT_ERROR_NO_SUPPORT_FONTSET);
|
return release_library_and_clear_out(ORBIS_FONT_ERROR_NO_SUPPORT_FONTSET);
|
||||||
@ -4331,8 +4263,8 @@ s32 PS4_SYSV_ABI sceFontOpenFontSet(OrbisFontLib library, u32 fontSetType, u32 o
|
|||||||
|
|
||||||
std::vector<unsigned char> primary_bytes;
|
std::vector<unsigned char> primary_bytes;
|
||||||
if (!Internal::LoadFontFile(primary_path, primary_bytes)) {
|
if (!Internal::LoadFontFile(primary_path, primary_bytes)) {
|
||||||
LOG_ERROR(Lib_Font, "FONT_OPEN_FAILED path='{}' sysFontPath='{}'",
|
LOG_ERROR(Lib_Font, "FONT_OPEN_FAILED path='{}' fontsPath='{}'", primary_path.string(),
|
||||||
primary_path.string(), Config::getSysFontPath().string());
|
Config::getFontsPath().string());
|
||||||
return release_library_and_clear_out(ORBIS_FONT_ERROR_FONT_OPEN_FAILED);
|
return release_library_and_clear_out(ORBIS_FONT_ERROR_FONT_OPEN_FAILED);
|
||||||
}
|
}
|
||||||
LOG_INFO(Lib_Font, "OpenFontSet: stage=loaded_primary_bytes");
|
LOG_INFO(Lib_Font, "OpenFontSet: stage=loaded_primary_bytes");
|
||||||
@ -4561,23 +4493,6 @@ s32 PS4_SYSV_ABI sceFontOpenFontSet(OrbisFontLib library, u32 fontSetType, u32 o
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto resolve_override =
|
|
||||||
[&](const std::string& key) -> std::optional<std::filesystem::path> {
|
|
||||||
if (auto override_path = Config::getSystemFontOverride(key)) {
|
|
||||||
if (!override_path->empty() && override_path->is_absolute()) {
|
|
||||||
return *override_path;
|
|
||||||
}
|
|
||||||
if (!override_path->empty() && !override_path->has_parent_path()) {
|
|
||||||
return base_dir / *override_path;
|
|
||||||
}
|
|
||||||
LOG_ERROR(Lib_Font,
|
|
||||||
"SystemFonts: override for '{}' must be a filename only or absolute "
|
|
||||||
"path: '{}'",
|
|
||||||
key, override_path->string());
|
|
||||||
}
|
|
||||||
return std::nullopt;
|
|
||||||
};
|
|
||||||
|
|
||||||
auto lower_ascii = [](std::string s) {
|
auto lower_ascii = [](std::string s) {
|
||||||
for (auto& c : s) {
|
for (auto& c : s) {
|
||||||
c = static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
|
c = static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
|
||||||
@ -4870,82 +4785,6 @@ s32 PS4_SYSV_ABI sceFontOpenFontSet(OrbisFontLib library, u32 fontSetType, u32 o
|
|||||||
: "SCEPS4Yoongd-Medium.otf");
|
: "SCEPS4Yoongd-Medium.otf");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 8; ++i) {
|
|
||||||
const std::string key_a =
|
|
||||||
fmt::format("fontset_0x{:08X}_fallback{}", fontSetType, i);
|
|
||||||
const std::string key_b =
|
|
||||||
fmt::format("fontSet_0x{:08X}_fallback{}", fontSetType, i);
|
|
||||||
std::optional<std::filesystem::path> p = resolve_override(key_a);
|
|
||||||
if (!p) {
|
|
||||||
p = resolve_override(key_b);
|
|
||||||
}
|
|
||||||
if (!p || p->empty()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<std::filesystem::path> p_resolved;
|
|
||||||
if (p->is_absolute()) {
|
|
||||||
std::error_code ec;
|
|
||||||
if (std::filesystem::exists(*p, ec)) {
|
|
||||||
p_resolved = *p;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
p_resolved = resolve_sysfont_path(*p);
|
|
||||||
}
|
|
||||||
if (!p_resolved) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<unsigned char> fb_bytes;
|
|
||||||
if (!Internal::LoadFontFile(*p_resolved, fb_bytes)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Internal::FontState::SystemFallbackFace fb{};
|
|
||||||
fb.font_id = 0xffffffffu;
|
|
||||||
fb.scale_factor = 1.0f;
|
|
||||||
fb.shift_value = 0;
|
|
||||||
fb.path = *p_resolved;
|
|
||||||
fb.bytes = std::make_shared<std::vector<unsigned char>>(std::move(fb_bytes));
|
|
||||||
fb.ft_face = Internal::CreateFreeTypeFaceFromBytes(
|
|
||||||
fb.bytes->data(), fb.bytes->size(), sub_font_index);
|
|
||||||
fb.ready = (fb.ft_face != nullptr);
|
|
||||||
if (fb.ready) {
|
|
||||||
fb.scale_factor = compute_sysfont_scale_factor(
|
|
||||||
fb.ft_face, fb.ft_face ? static_cast<int>(fb.ft_face->units_per_EM) : 0);
|
|
||||||
fb.shift_value = compute_sysfont_shift_value(fb.ft_face);
|
|
||||||
LOG_DEBUG(
|
|
||||||
Lib_Font,
|
|
||||||
"SystemFonts: fallback='{}' unitsPerEm={} scaleFactor={} shiftValue={}",
|
|
||||||
fb.path.filename().string(),
|
|
||||||
fb.ft_face ? static_cast<int>(fb.ft_face->units_per_EM) : 0,
|
|
||||||
fb.scale_factor, fb.shift_value);
|
|
||||||
st.system_fallback_faces.push_back(std::move(fb));
|
|
||||||
} else {
|
|
||||||
Internal::DestroyFreeTypeFace(fb.ft_face);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const std::string global_fallback_name = Config::getSystemFontFallbackName();
|
|
||||||
if (!global_fallback_name.empty()) {
|
|
||||||
const auto existing_name = primary_path.filename().string();
|
|
||||||
if (existing_name != global_fallback_name) {
|
|
||||||
std::filesystem::path fb_path = global_fallback_name;
|
|
||||||
if (!fb_path.is_absolute()) {
|
|
||||||
fb_path = base_dir / global_fallback_name;
|
|
||||||
}
|
|
||||||
if (const auto resolved_path = resolve_sysfont_path(fb_path)) {
|
|
||||||
const std::string fb_lower =
|
|
||||||
lower_ascii(resolved_path->filename().string());
|
|
||||||
if (!has_fallback_name_lower(fb_lower)) {
|
|
||||||
add_fallback_face(*resolved_path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -6928,16 +6767,6 @@ s32 PS4_SYSV_ABI sceFontSupportSystemFonts(OrbisFontLib library) {
|
|||||||
ls.owned_sysfonts_ctx = ctx;
|
ls.owned_sysfonts_ctx = ctx;
|
||||||
ls.owned_sysfonts_ctx_size = kSysCtxSize;
|
ls.owned_sysfonts_ctx_size = kSysCtxSize;
|
||||||
|
|
||||||
if (!Internal::g_mnt) {
|
|
||||||
Internal::g_mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance();
|
|
||||||
}
|
|
||||||
if (Internal::g_mnt) {
|
|
||||||
const auto sysfont_base = GetSysFontBaseDir();
|
|
||||||
if (!sysfont_base.empty() && !Internal::g_mnt->GetMount("/:dev_font:")) {
|
|
||||||
Internal::g_mnt->Mount(sysfont_base, "/:dev_font:", true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReleaseLibraryLock(lib, prev_lock_word);
|
ReleaseLibraryLock(lib, prev_lock_word);
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1528,94 +1528,31 @@ static bool DirectoryContainsAnyFontFiles(const std::filesystem::path& dir) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::optional<std::filesystem::path> FindChildDirContainingFile(
|
|
||||||
const std::filesystem::path& base_dir, const std::string& filename) {
|
|
||||||
if (filename.empty()) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::error_code ec;
|
|
||||||
if (!std::filesystem::is_directory(base_dir, ec)) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<std::filesystem::path> match;
|
|
||||||
for (const auto& entry : std::filesystem::directory_iterator(base_dir, ec)) {
|
|
||||||
if (ec) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
if (!entry.is_directory(ec) || ec) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const auto candidate = entry.path() / filename;
|
|
||||||
if (std::filesystem::is_regular_file(candidate, ec) && !ec) {
|
|
||||||
if (match) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
match = entry.path();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return match;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::filesystem::path GetSysFontBaseDir() {
|
std::filesystem::path GetSysFontBaseDir() {
|
||||||
std::filesystem::path base = Config::getSysFontPath();
|
std::filesystem::path base = Config::getFontsPath();
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
if (base.empty()) {
|
if (base.empty()) {
|
||||||
LOG_ERROR(Lib_Font, "SystemFonts: SysFontPath not set");
|
LOG_ERROR(Lib_Font, "SystemFonts: FontsPath not set");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
if (std::filesystem::is_directory(base, ec)) {
|
if (std::filesystem::is_directory(base, ec)) {
|
||||||
if (DirectoryContainsAnyFontFiles(base)) {
|
const auto font_dir = base / "font";
|
||||||
|
const auto font2_dir = base / "font2";
|
||||||
|
if (DirectoryContainsAnyFontFiles(base) || DirectoryContainsAnyFontFiles(font_dir) ||
|
||||||
|
DirectoryContainsAnyFontFiles(font2_dir)) {
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
const auto font_dir = base / "font";
|
|
||||||
const auto font2_dir = base / "font2";
|
|
||||||
if (DirectoryContainsAnyFontFiles(font_dir) ||
|
|
||||||
DirectoryContainsAnyFontFiles(font2_dir)) {
|
|
||||||
return base;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string fallback = Config::getSystemFontFallbackName();
|
|
||||||
if (auto child = FindChildDirContainingFile(base, fallback)) {
|
|
||||||
return *child;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<std::filesystem::path> sole_font_dir;
|
|
||||||
for (const auto& entry : std::filesystem::directory_iterator(base, ec)) {
|
|
||||||
if (ec) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!entry.is_directory(ec) || ec) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (DirectoryContainsAnyFontFiles(entry.path())) {
|
|
||||||
if (sole_font_dir) {
|
|
||||||
sole_font_dir.reset();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
sole_font_dir = entry.path();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sole_font_dir) {
|
|
||||||
return *sole_font_dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_ERROR(
|
LOG_ERROR(
|
||||||
Lib_Font,
|
Lib_Font,
|
||||||
"SystemFonts: SysFontPath '{}' contains no font files; set it to the directory that "
|
"SystemFonts: FontsPath '{}' contains no font files; expected files directly in this "
|
||||||
"contains the .otf/.ttf files (or ensure [SystemFonts].fallback is present in exactly "
|
"directory or under 'font'/'font2'",
|
||||||
"one child directory)",
|
|
||||||
base.string());
|
base.string());
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
if (std::filesystem::is_regular_file(base, ec)) {
|
if (std::filesystem::is_regular_file(base, ec)) {
|
||||||
return base.parent_path();
|
return base.parent_path();
|
||||||
}
|
}
|
||||||
LOG_ERROR(Lib_Font, "SystemFonts: SysFontPath '{}' is not a valid directory or file",
|
LOG_ERROR(Lib_Font, "SystemFonts: FontsPath '{}' is not a valid directory or file",
|
||||||
base.string());
|
base.string());
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -1658,75 +1595,12 @@ static std::filesystem::path ResolveSystemFontPathCandidate(const std::filesyste
|
|||||||
return direct;
|
return direct;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string MacroToCamel(const char* macro_key) {
|
|
||||||
if (!macro_key) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
std::string s(macro_key);
|
|
||||||
const std::string prefix = "FONTSET_";
|
|
||||||
if (s.rfind(prefix, 0) != 0) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
std::string out = "FontSet";
|
|
||||||
size_t pos = prefix.size();
|
|
||||||
while (pos < s.size()) {
|
|
||||||
size_t next = s.find('_', pos);
|
|
||||||
const size_t len = (next == std::string::npos) ? (s.size() - pos) : (next - pos);
|
|
||||||
std::string token = s.substr(pos, len);
|
|
||||||
for (auto& c : token) {
|
|
||||||
c = static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
|
|
||||||
}
|
|
||||||
if (!token.empty()) {
|
|
||||||
token[0] = static_cast<char>(std::toupper(static_cast<unsigned char>(token[0])));
|
|
||||||
}
|
|
||||||
out += token;
|
|
||||||
if (next == std::string::npos) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
pos = next + 1;
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::filesystem::path ResolveSystemFontPath(u32 font_set_type) {
|
std::filesystem::path ResolveSystemFontPath(u32 font_set_type) {
|
||||||
if (const auto* def = FindSystemFontDefinition(font_set_type); def) {
|
if (const auto* def = FindSystemFontDefinition(font_set_type); def) {
|
||||||
const auto base_dir = GetSysFontBaseDir();
|
const auto base_dir = GetSysFontBaseDir();
|
||||||
if (base_dir.empty()) {
|
if (base_dir.empty()) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
if (auto override_path = Config::getSystemFontOverride(def->config_key)) {
|
|
||||||
if (!override_path->empty() && !override_path->is_absolute() &&
|
|
||||||
!override_path->has_parent_path()) {
|
|
||||||
return ResolveSystemFontPathCandidate(base_dir, *override_path);
|
|
||||||
}
|
|
||||||
LOG_ERROR(Lib_Font,
|
|
||||||
"SystemFonts: override for '{}' must be a filename only (no path): '{}'",
|
|
||||||
def->config_key, override_path->string());
|
|
||||||
}
|
|
||||||
const auto camel_key = MacroToCamel(def->config_key);
|
|
||||||
if (!camel_key.empty()) {
|
|
||||||
if (auto override_path2 = Config::getSystemFontOverride(camel_key)) {
|
|
||||||
if (!override_path2->empty() && !override_path2->is_absolute() &&
|
|
||||||
!override_path2->has_parent_path()) {
|
|
||||||
return ResolveSystemFontPathCandidate(base_dir, *override_path2);
|
|
||||||
}
|
|
||||||
LOG_ERROR(Lib_Font,
|
|
||||||
"SystemFonts: override for '{}' must be a filename only (no path): '{}'",
|
|
||||||
camel_key, override_path2->string());
|
|
||||||
}
|
|
||||||
std::string lower_camel = camel_key;
|
|
||||||
lower_camel[0] =
|
|
||||||
static_cast<char>(std::tolower(static_cast<unsigned char>(lower_camel[0])));
|
|
||||||
if (auto override_path3 = Config::getSystemFontOverride(lower_camel)) {
|
|
||||||
if (!override_path3->empty() && !override_path3->is_absolute() &&
|
|
||||||
!override_path3->has_parent_path()) {
|
|
||||||
return ResolveSystemFontPathCandidate(base_dir, *override_path3);
|
|
||||||
}
|
|
||||||
LOG_ERROR(Lib_Font,
|
|
||||||
"SystemFonts: override for '{}' must be a filename only (no path): '{}'",
|
|
||||||
lower_camel, override_path3->string());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (def->default_file && *def->default_file) {
|
if (def->default_file && *def->default_file) {
|
||||||
return ResolveSystemFontPathCandidate(base_dir, def->default_file);
|
return ResolveSystemFontPathCandidate(base_dir, def->default_file);
|
||||||
}
|
}
|
||||||
@ -1735,45 +1609,6 @@ std::filesystem::path ResolveSystemFontPath(u32 font_set_type) {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::filesystem::path ResolveSystemFontPathFromConfigOnly(u32 font_set_type) {
|
|
||||||
const auto base_dir = GetSysFontBaseDir();
|
|
||||||
if (base_dir.empty()) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string key_a = fmt::format("fontset_0x{:08X}", font_set_type);
|
|
||||||
const std::string key_b = fmt::format("fontSet_0x{:08X}", font_set_type);
|
|
||||||
|
|
||||||
auto try_key = [&](const std::string& key) -> std::optional<std::filesystem::path> {
|
|
||||||
if (auto override_path = Config::getSystemFontOverride(key)) {
|
|
||||||
if (!override_path->empty() && override_path->is_absolute()) {
|
|
||||||
return *override_path;
|
|
||||||
}
|
|
||||||
if (!override_path->empty() && !override_path->has_parent_path()) {
|
|
||||||
return base_dir / *override_path;
|
|
||||||
}
|
|
||||||
LOG_ERROR(
|
|
||||||
Lib_Font,
|
|
||||||
"SystemFonts: override for '{}' must be a filename only or absolute path: '{}'",
|
|
||||||
key, override_path->string());
|
|
||||||
}
|
|
||||||
return std::nullopt;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (auto p = try_key(key_a)) {
|
|
||||||
return *p;
|
|
||||||
}
|
|
||||||
if (auto p = try_key(key_b)) {
|
|
||||||
return *p;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string fallback = Config::getSystemFontFallbackName();
|
|
||||||
if (!fallback.empty()) {
|
|
||||||
return base_dir / fallback;
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
const FontSetCache* EnsureFontSetCache(u32 font_set_type) {
|
const FontSetCache* EnsureFontSetCache(u32 font_set_type) {
|
||||||
if (font_set_type == 0) {
|
if (font_set_type == 0) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -1872,10 +1707,7 @@ bool AttachSystemFont(FontState& st, Libraries::Font::OrbisFontHandle handle) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::filesystem::path primary_path = ResolveSystemFontPathFromConfigOnly(st.font_set_type);
|
std::filesystem::path primary_path = ResolveSystemFontPath(st.font_set_type);
|
||||||
if (primary_path.empty()) {
|
|
||||||
primary_path = ResolveSystemFontPath(st.font_set_type);
|
|
||||||
}
|
|
||||||
std::vector<unsigned char> primary_bytes;
|
std::vector<unsigned char> primary_bytes;
|
||||||
if (primary_path.empty() || !LoadFontFile(primary_path, primary_bytes)) {
|
if (primary_path.empty() || !LoadFontFile(primary_path, primary_bytes)) {
|
||||||
return false;
|
return false;
|
||||||
@ -1901,80 +1733,6 @@ bool AttachSystemFont(FontState& st, Libraries::Font::OrbisFontHandle handle) {
|
|||||||
st.system_font_path = primary_path;
|
st.system_font_path = primary_path;
|
||||||
st.system_requested = true;
|
st.system_requested = true;
|
||||||
|
|
||||||
const auto base_dir = GetSysFontBaseDir();
|
|
||||||
if (!base_dir.empty()) {
|
|
||||||
auto resolve_override =
|
|
||||||
[&](const std::string& key) -> std::optional<std::filesystem::path> {
|
|
||||||
if (auto override_path = Config::getSystemFontOverride(key)) {
|
|
||||||
if (!override_path->empty() && override_path->is_absolute()) {
|
|
||||||
return *override_path;
|
|
||||||
}
|
|
||||||
if (!override_path->empty() && !override_path->has_parent_path()) {
|
|
||||||
return base_dir / *override_path;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return std::nullopt;
|
|
||||||
};
|
|
||||||
|
|
||||||
for (int i = 0; i < 8; ++i) {
|
|
||||||
const std::string key_a =
|
|
||||||
fmt::format("fontset_0x{:08X}_fallback{}", st.font_set_type, i);
|
|
||||||
const std::string key_b =
|
|
||||||
fmt::format("fontSet_0x{:08X}_fallback{}", st.font_set_type, i);
|
|
||||||
std::optional<std::filesystem::path> p = resolve_override(key_a);
|
|
||||||
if (!p) {
|
|
||||||
p = resolve_override(key_b);
|
|
||||||
}
|
|
||||||
if (!p || p->empty()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<unsigned char> fb_bytes;
|
|
||||||
if (!LoadFontFile(*p, fb_bytes)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
FontState::SystemFallbackFace fb{};
|
|
||||||
fb.font_id = static_cast<u32>(i + 1);
|
|
||||||
fb.scale_factor = 1.0f;
|
|
||||||
fb.shift_value = 0;
|
|
||||||
fb.path = *p;
|
|
||||||
fb.bytes = std::make_shared<std::vector<unsigned char>>(std::move(fb_bytes));
|
|
||||||
fb.ft_face =
|
|
||||||
CreateFreeTypeFaceFromBytes(fb.bytes->data(), fb.bytes->size(), subfont_index);
|
|
||||||
fb.ready = (fb.ft_face != nullptr);
|
|
||||||
if (fb.ready) {
|
|
||||||
st.system_fallback_faces.push_back(std::move(fb));
|
|
||||||
} else {
|
|
||||||
DestroyFreeTypeFace(fb.ft_face);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string global_fallback_name = Config::getSystemFontFallbackName();
|
|
||||||
if (!global_fallback_name.empty()) {
|
|
||||||
const auto existing_name = primary_path.filename().string();
|
|
||||||
if (existing_name != global_fallback_name) {
|
|
||||||
const std::filesystem::path fb_path = base_dir / global_fallback_name;
|
|
||||||
std::vector<unsigned char> fb_bytes;
|
|
||||||
if (LoadFontFile(fb_path, fb_bytes)) {
|
|
||||||
FontState::SystemFallbackFace fb{};
|
|
||||||
fb.font_id = 0xFFFFFFFFu;
|
|
||||||
fb.scale_factor = 1.0f;
|
|
||||||
fb.shift_value = 0;
|
|
||||||
fb.path = fb_path;
|
|
||||||
fb.bytes = std::make_shared<std::vector<unsigned char>>(std::move(fb_bytes));
|
|
||||||
fb.ft_face = CreateFreeTypeFaceFromBytes(fb.bytes->data(), fb.bytes->size(),
|
|
||||||
subfont_index);
|
|
||||||
fb.ready = (fb.ft_face != nullptr);
|
|
||||||
if (fb.ready) {
|
|
||||||
st.system_fallback_faces.push_back(std::move(fb));
|
|
||||||
} else {
|
|
||||||
DestroyFreeTypeFace(fb.ft_face);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_INFO(Lib_Font, "system font attached");
|
LOG_INFO(Lib_Font, "system font attached");
|
||||||
LOG_DEBUG(Lib_Font,
|
LOG_DEBUG(Lib_Font,
|
||||||
"system font attach params:\n"
|
"system font attach params:\n"
|
||||||
@ -1994,8 +1752,8 @@ std::string ReportSystemFaceRequest(FontState& st, Libraries::Font::OrbisFontHan
|
|||||||
}
|
}
|
||||||
if (!st.system_requested) {
|
if (!st.system_requested) {
|
||||||
st.system_requested = true;
|
st.system_requested = true;
|
||||||
const auto configured = Config::getSysFontPath();
|
const auto configured = Config::getFontsPath();
|
||||||
return fmt::format("SystemFace: handle={} requested internal font but sysFontPath ('{}') "
|
return fmt::format("SystemFace: handle={} requested internal font but fontsPath ('{}') "
|
||||||
"could not be loaded",
|
"could not be loaded",
|
||||||
static_cast<const void*>(handle), configured.string());
|
static_cast<const void*>(handle), configured.string());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -748,9 +748,7 @@ const GlyphEntry* GetGlyphEntry(FontState& st, Libraries::Font::OrbisFontHandle
|
|||||||
FT_Face& face_out, float& scale_out);
|
FT_Face& face_out, float& scale_out);
|
||||||
const SystemFontDefinition* FindSystemFontDefinition(u32 font_set_type);
|
const SystemFontDefinition* FindSystemFontDefinition(u32 font_set_type);
|
||||||
std::filesystem::path GetSysFontBaseDir();
|
std::filesystem::path GetSysFontBaseDir();
|
||||||
std::string MacroToCamel(const char* macro_key);
|
|
||||||
std::filesystem::path ResolveSystemFontPath(u32 font_set_type);
|
std::filesystem::path ResolveSystemFontPath(u32 font_set_type);
|
||||||
std::filesystem::path ResolveSystemFontPathFromConfigOnly(u32 font_set_type);
|
|
||||||
const struct FontSetCache* EnsureFontSetCache(u32 font_set_type);
|
const struct FontSetCache* EnsureFontSetCache(u32 font_set_type);
|
||||||
bool HasSfntTables(const std::vector<unsigned char>& bytes);
|
bool HasSfntTables(const std::vector<unsigned char>& bytes);
|
||||||
bool LoadFontFile(const std::filesystem::path& path, std::vector<unsigned char>& out_bytes);
|
bool LoadFontFile(const std::filesystem::path& path, std::vector<unsigned char>& out_bytes);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user