mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-04-29 23:41:19 -06:00
Add system font path and override config support
Introduce new config options for system font directory, fallback font name, and per-font overrides. Update config load/save logic to handle a [SystemFonts] TOML section, supporting both fallback and individual font overrides. Improve user instructions for custom font setup and clarify related code comments. These changes enhance flexibility and user experience for system font configuration.
This commit is contained in:
parent
a30014fbfc
commit
296e4385c4
@ -4,8 +4,9 @@
|
||||
#include <fstream>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/xchar.h> // for wstring support
|
||||
#include <toml.hpp>
|
||||
|
||||
#include "common/assert.h"
|
||||
@ -144,6 +145,9 @@ static ConfigEntry<string> isSideTrophy("right");
|
||||
static ConfigEntry<bool> isConnectedToNetwork(false);
|
||||
static bool enableDiscordRPC = false;
|
||||
static std::filesystem::path sys_modules_path = {};
|
||||
static std::filesystem::path sys_font_path = {};
|
||||
static std::string sys_font_fallback_name = {};
|
||||
static std::unordered_map<std::string, std::filesystem::path> system_font_overrides;
|
||||
|
||||
// Input
|
||||
static ConfigEntry<int> cursorState(HideCursorState::Idle);
|
||||
@ -234,6 +238,47 @@ void setSysModulesPath(const std::filesystem::path& path) {
|
||||
sys_modules_path = path;
|
||||
}
|
||||
|
||||
std::filesystem::path getSysFontPath() {
|
||||
if (sys_font_path.empty()) {
|
||||
return Common::FS::GetUserPath(Common::FS::PathType::FontDir);
|
||||
}
|
||||
return sys_font_path;
|
||||
}
|
||||
|
||||
void setSysFontPath(const std::filesystem::path& path) {
|
||||
sys_font_path = path;
|
||||
}
|
||||
|
||||
std::optional<std::filesystem::path> getSystemFontOverride(std::string_view key) {
|
||||
if (key.empty()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
auto it = system_font_overrides.find(std::string(key));
|
||||
if (it == system_font_overrides.end()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
std::string getSystemFontFallbackName() {
|
||||
return sys_font_fallback_name;
|
||||
}
|
||||
|
||||
void setSystemFontFallbackName(const std::string& name) {
|
||||
sys_font_fallback_name = name;
|
||||
}
|
||||
|
||||
void setSystemFontOverride(std::string_view key, const std::filesystem::path& path) {
|
||||
if (key.empty()) {
|
||||
return;
|
||||
}
|
||||
system_font_overrides[std::string(key)] = path;
|
||||
}
|
||||
|
||||
void clearSystemFontOverrides() {
|
||||
system_font_overrides.clear();
|
||||
}
|
||||
|
||||
int getVolumeSlider() {
|
||||
return volumeSlider.get();
|
||||
}
|
||||
@ -460,7 +505,7 @@ void setShowFpsCounter(bool enable, bool is_game_specific) {
|
||||
showFpsCounter.set(enable, is_game_specific);
|
||||
}
|
||||
|
||||
bool isLoggingEnabled() {
|
||||
static bool isLoggingEnabled() {
|
||||
return logEnabled.get();
|
||||
}
|
||||
|
||||
@ -862,6 +907,10 @@ void load(const std::filesystem::path& path, bool is_game_specific) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_game_specific) {
|
||||
system_font_overrides.clear();
|
||||
}
|
||||
|
||||
if (data.contains("General")) {
|
||||
const toml::value& general = data.at("General");
|
||||
|
||||
@ -885,6 +934,43 @@ void load(const std::filesystem::path& path, bool is_game_specific) {
|
||||
isConnectedToNetwork.setFromToml(general, "isConnectedToNetwork", is_game_specific);
|
||||
defaultControllerID.setFromToml(general, "defaultControllerID", is_game_specific);
|
||||
sys_modules_path = toml::find_fs_path_or(general, "sysModulesPath", sys_modules_path);
|
||||
// Accept alias without trailing 's'
|
||||
sys_modules_path = toml::find_fs_path_or(general, "sysModulePath", sys_modules_path);
|
||||
// Prefer 'sysFontPath'; accept 'SysFontPath' for compatibility
|
||||
sys_font_path = toml::find_fs_path_or(general, "sysFontPath", sys_font_path);
|
||||
sys_font_path = toml::find_fs_path_or(general, "SysFontPath", sys_font_path);
|
||||
}
|
||||
|
||||
if (data.contains("SystemFonts")) {
|
||||
const toml::value& fonts = data.at("SystemFonts");
|
||||
if (fonts.is_table()) {
|
||||
// Read fallback (lowercase preferred), accept 'Fallback'/'FallbackFontName' for compat
|
||||
if (fonts.contains("fallback")) {
|
||||
const auto& v = fonts.at("fallback");
|
||||
if (v.is_string()) {
|
||||
sys_font_fallback_name = toml::get<std::string>(v);
|
||||
}
|
||||
} else if (fonts.contains("Fallback")) {
|
||||
const auto& v = fonts.at("Fallback");
|
||||
if (v.is_string()) {
|
||||
sys_font_fallback_name = toml::get<std::string>(v);
|
||||
}
|
||||
} else if (fonts.contains("FallbackFontName")) {
|
||||
const auto& v = fonts.at("FallbackFontName");
|
||||
if (v.is_string()) {
|
||||
sys_font_fallback_name = toml::get<std::string>(v);
|
||||
}
|
||||
}
|
||||
for (const auto& [name, value] : fonts.as_table()) {
|
||||
if (name == "fallback" || name == "Fallback" || name == "FallbackFontName") {
|
||||
continue;
|
||||
}
|
||||
if (value.is_string()) {
|
||||
system_font_overrides[name] =
|
||||
std::filesystem::path(toml::get<std::string>(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (data.contains("Input")) {
|
||||
@ -1005,7 +1091,7 @@ void load(const std::filesystem::path& path, bool is_game_specific) {
|
||||
}
|
||||
}
|
||||
|
||||
void sortTomlSections(toml::ordered_value& data) {
|
||||
static void sortTomlSections(toml::ordered_value& data) {
|
||||
toml::ordered_value ordered_data;
|
||||
std::vector<string> section_order = {"General", "Input", "Audio", "GPU", "Vulkan",
|
||||
"Debug", "Keys", "GUI", "Settings"};
|
||||
@ -1158,6 +1244,22 @@ void save(const std::filesystem::path& path, bool is_game_specific) {
|
||||
// Non game-specific entries
|
||||
data["General"]["enableDiscordRPC"] = enableDiscordRPC;
|
||||
data["General"]["sysModulesPath"] = string{fmt::UTF(sys_modules_path.u8string()).data};
|
||||
// Save using 'sysFontPath' to match style
|
||||
data["General"]["sysFontPath"] = string{fmt::UTF(sys_font_path.u8string()).data};
|
||||
{
|
||||
toml::table fonts_table;
|
||||
if (!sys_font_fallback_name.empty()) {
|
||||
fonts_table["fallback"] = sys_font_fallback_name;
|
||||
}
|
||||
for (const auto& [name, path_override] : system_font_overrides) {
|
||||
fonts_table[name] = string{fmt::UTF(path_override.u8string()).data};
|
||||
}
|
||||
if (!fonts_table.empty()) {
|
||||
data["SystemFonts"] = fonts_table;
|
||||
} else if (data.is_table()) {
|
||||
data.as_table().erase("SystemFonts");
|
||||
}
|
||||
}
|
||||
data["GUI"]["installDirs"] = install_dirs;
|
||||
data["GUI"]["installDirsEnabled"] = install_dirs_enabled;
|
||||
data["GUI"]["saveDataPath"] = string{fmt::UTF(save_data_path.u8string()).data};
|
||||
@ -1302,7 +1404,7 @@ hotkey_quit = lctrl, lshift, end
|
||||
)";
|
||||
}
|
||||
|
||||
constexpr std::string_view GetDefaultInputConfig() {
|
||||
static constexpr std::string_view GetDefaultInputConfig() {
|
||||
return R"(#Feeling lost? Check out the Help section!
|
||||
|
||||
# Keyboard bindings
|
||||
|
||||
@ -129,7 +129,6 @@ static auto UserPaths = [] {
|
||||
create_path(PathType::CustomConfigs, user_dir / CUSTOM_CONFIGS);
|
||||
create_path(PathType::CacheDir, user_dir / CACHE_DIR);
|
||||
create_path(PathType::FontDir, user_dir / SYSFONTS_DIR);
|
||||
// subdirectory for fonts
|
||||
std::filesystem::create_directory(user_dir / SYSFONTS_DIR / "font");
|
||||
std::filesystem::create_directory(user_dir / SYSFONTS_DIR / "font2");
|
||||
|
||||
@ -148,11 +147,15 @@ static auto UserPaths = [] {
|
||||
notice_file.close();
|
||||
}
|
||||
|
||||
std::ofstream font_instructions(user_dir / SYSFONTS_DIR / "Instructions.txt");
|
||||
if (font_instructions.is_open()) {
|
||||
font_instructions << "Place /preinst/common/font contents into font folder\n"
|
||||
"Place /system/common/font2 contents into font2 folder\n";
|
||||
font_instructions.close();
|
||||
const auto instructions_path = user_dir / SYSFONTS_DIR / "Instructions.txt";
|
||||
std::error_code ec;
|
||||
if (!std::filesystem::exists(instructions_path, ec)) {
|
||||
std::ofstream font_instructions(instructions_path);
|
||||
if (font_instructions.is_open()) {
|
||||
font_instructions << "Place system font files (.otf/.ttf) into the 'font' and 'font2' "
|
||||
"folders.\n";
|
||||
font_instructions.close();
|
||||
}
|
||||
}
|
||||
|
||||
return paths;
|
||||
|
||||
@ -25,7 +25,7 @@ enum class PathType {
|
||||
CustomTrophy, // Where custom files for trophies are stored.
|
||||
CustomConfigs, // Where custom files for different games are stored.
|
||||
CacheDir, // Where pipeline and shader cache is stored.
|
||||
FontDir // Where font files are stored.
|
||||
FontDir, // Where system font files are stored.
|
||||
};
|
||||
|
||||
constexpr auto PORTABLE_DIR = "user";
|
||||
|
||||
Loading…
Reference in New Issue
Block a user