[UI] Allow loading custom font & changed default font on Windows
- Unified font size to 12. This causes default UI to look a bit bigger - Set oversample to 2 to make font more readable (especially custom fonts)
This commit is contained in:
parent
c5e6352c34
commit
6c0d1f94df
|
@ -36,6 +36,7 @@ enum class SimpleMessageBoxType {
|
|||
// This is expected to block the caller until the message box is closed.
|
||||
void ShowSimpleMessageBox(SimpleMessageBoxType type, std::string_view message);
|
||||
|
||||
const std::filesystem::path GetFontPath(const std::string font_name);
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_BASE_SYSTEM_H_
|
||||
|
|
|
@ -294,4 +294,8 @@ void ShowSimpleMessageBox(SimpleMessageBoxType type, std::string_view message) {
|
|||
// Java VM for the calling thread is needed.
|
||||
}
|
||||
|
||||
const std::filesystem::path GetFontPath(const std::string font_name) {
|
||||
return "";
|
||||
}
|
||||
|
||||
} // namespace xe
|
||||
|
|
|
@ -67,4 +67,8 @@ void ShowSimpleMessageBox(SimpleMessageBoxType type, std::string_view message) {
|
|||
}
|
||||
}
|
||||
|
||||
const std::filesystem::path GetFontPath(const std::string font_name) {
|
||||
return "";
|
||||
}
|
||||
|
||||
} // namespace xe
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include <ShlObj_core.h>
|
||||
|
||||
#include "xenia/base/platform_win.h"
|
||||
#include "xenia/base/string.h"
|
||||
#include "xenia/base/system.h"
|
||||
|
@ -48,4 +50,25 @@ void ShowSimpleMessageBox(SimpleMessageBoxType type,
|
|||
type_flags);
|
||||
}
|
||||
|
||||
const std::filesystem::path GetFontPath(const std::string font_name) {
|
||||
std::filesystem::path font_path = "";
|
||||
|
||||
PWSTR fonts_dir;
|
||||
HRESULT result = SHGetKnownFolderPath(FOLDERID_Fonts, 0, NULL, &fonts_dir);
|
||||
if (FAILED(result)) {
|
||||
CoTaskMemFree(static_cast<void*>(fonts_dir));
|
||||
return "";
|
||||
}
|
||||
font_path = std::wstring(fonts_dir);
|
||||
font_path.append(font_name);
|
||||
|
||||
CoTaskMemFree(static_cast<void*>(fonts_dir));
|
||||
|
||||
if (!std::filesystem::exists(font_path)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return font_path;
|
||||
}
|
||||
|
||||
} // namespace xe
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <cstring>
|
||||
|
||||
#include "third_party/imgui/imgui.h"
|
||||
#include "xenia/base/system.h"
|
||||
#include "xenia/base/assert.h"
|
||||
#include "xenia/base/clock.h"
|
||||
#include "xenia/base/logging.h"
|
||||
|
@ -21,6 +22,11 @@
|
|||
#include "xenia/ui/ui_event.h"
|
||||
#include "xenia/ui/window.h"
|
||||
|
||||
DEFINE_path(
|
||||
custom_font_path, "",
|
||||
"Allows user to load custom font and use it instead of default one.", "UI");
|
||||
DEFINE_uint32(font_size, 12, "Allows user to set custom font size.", "UI");
|
||||
|
||||
namespace xe {
|
||||
namespace ui {
|
||||
|
||||
|
@ -98,38 +104,7 @@ void ImGuiDrawer::Initialize() {
|
|||
internal_state_ = ImGui::CreateContext();
|
||||
ImGui::SetCurrentContext(internal_state_);
|
||||
|
||||
auto& io = ImGui::GetIO();
|
||||
|
||||
// TODO(gibbed): disable imgui.ini saving for now,
|
||||
// imgui assumes paths are char* so we can't throw a good path at it on
|
||||
// Windows.
|
||||
io.IniFilename = nullptr;
|
||||
|
||||
// Setup the font glyphs.
|
||||
ImFontConfig font_config;
|
||||
font_config.OversampleH = font_config.OversampleV = 1;
|
||||
font_config.PixelSnapH = true;
|
||||
static const ImWchar font_glyph_ranges[] = {
|
||||
0x0020,
|
||||
0x00FF, // Basic Latin + Latin Supplement
|
||||
0,
|
||||
};
|
||||
io.Fonts->AddFontFromMemoryCompressedBase85TTF(
|
||||
kProggyTinyCompressedDataBase85, 10.0f, &font_config, font_glyph_ranges);
|
||||
// TODO(benvanik): jp font on other platforms?
|
||||
// https://github.com/Koruri/kibitaki looks really good, but is 1.5MiB.
|
||||
const char* jp_font_path = "C:\\Windows\\Fonts\\msgothic.ttc";
|
||||
if (std::filesystem::exists(jp_font_path)) {
|
||||
ImFontConfig jp_font_config;
|
||||
jp_font_config.MergeMode = true;
|
||||
jp_font_config.OversampleH = jp_font_config.OversampleV = 1;
|
||||
jp_font_config.PixelSnapH = true;
|
||||
jp_font_config.FontNo = 0;
|
||||
io.Fonts->AddFontFromFileTTF(jp_font_path, 12.0f, &jp_font_config,
|
||||
io.Fonts->GetGlyphRangesJapanese());
|
||||
} else {
|
||||
XELOGW("Unable to load Japanese font; JP characters will be boxes");
|
||||
}
|
||||
InitializeFonts();
|
||||
|
||||
auto& style = ImGui::GetStyle();
|
||||
style.ScrollbarRounding = 0;
|
||||
|
@ -218,6 +193,105 @@ std::optional<ImGuiKey> ImGuiDrawer::VirtualKeyToImGuiKey(VirtualKey vkey) {
|
|||
}
|
||||
}
|
||||
|
||||
static const ImWchar font_glyph_ranges[] = {
|
||||
0x0020, 0x00FF, // Basic Latin + Latin Supplement
|
||||
0x0370, 0x03FF, // Greek
|
||||
0x0400, 0x044F, // Cyrillic
|
||||
0x2000, 0x206F, // General Punctuation
|
||||
0,
|
||||
};
|
||||
|
||||
void ImGuiDrawer::LoadCustomFont(ImGuiIO& io, ImFontConfig& font_config,
|
||||
const float font_size) {
|
||||
if (cvars::custom_font_path.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!std::filesystem::exists(cvars::custom_font_path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string font_path = xe::path_to_utf8(cvars::custom_font_path);
|
||||
ImFont* font = io.Fonts->AddFontFromFileTTF(font_path.c_str(), font_size,
|
||||
&font_config, font_glyph_ranges);
|
||||
|
||||
io.Fonts->Build();
|
||||
|
||||
if (!font->IsLoaded()) {
|
||||
XELOGE("Failed to load custom font: {}", font_path);
|
||||
io.Fonts->Clear();
|
||||
}
|
||||
}
|
||||
|
||||
void ImGuiDrawer::LoadSystemFont(ImGuiIO& io, ImFontConfig& font_config,
|
||||
const float font_size) {
|
||||
const std::filesystem::path font_path = xe::GetFontPath("tahoma.ttf");
|
||||
if (!std::filesystem::exists(font_path)) {
|
||||
XELOGW(
|
||||
"Unable to find Tahoma font in OS fonts directory. Switching to "
|
||||
"embedded Xenia font");
|
||||
return;
|
||||
}
|
||||
|
||||
ImFont* font =
|
||||
io.Fonts->AddFontFromFileTTF(xe::path_to_utf8(font_path).c_str(),
|
||||
font_size, &font_config, font_glyph_ranges);
|
||||
|
||||
io.Fonts->Build();
|
||||
// Something went wrong while loading custom font. Probably corrupted.
|
||||
if (!font->IsLoaded()) {
|
||||
XELOGE("Failed to load custom font: {}", xe::path_to_utf8(font_path));
|
||||
io.Fonts->Clear();
|
||||
}
|
||||
}
|
||||
|
||||
void ImGuiDrawer::LoadJapaneseFont(ImGuiIO& io, const float font_size) {
|
||||
// TODO(benvanik): jp font on other platforms?
|
||||
const std::filesystem::path font_path = xe::GetFontPath("msgothic.ttc");
|
||||
|
||||
if (!std::filesystem::exists(font_path)) {
|
||||
XELOGW("Unable to load Japanese font; JP characters will be boxes");
|
||||
return;
|
||||
}
|
||||
|
||||
ImFontConfig jp_font_config;
|
||||
jp_font_config.MergeMode = true;
|
||||
jp_font_config.OversampleH = jp_font_config.OversampleV = 2;
|
||||
jp_font_config.PixelSnapH = true;
|
||||
jp_font_config.FontNo = 0;
|
||||
io.Fonts->AddFontFromFileTTF(xe::path_to_utf8(font_path).c_str(), font_size,
|
||||
&jp_font_config,
|
||||
io.Fonts->GetGlyphRangesJapanese());
|
||||
};
|
||||
|
||||
void ImGuiDrawer::InitializeFonts() {
|
||||
auto& io = ImGui::GetIO();
|
||||
|
||||
const float font_size = std::max((float)cvars::font_size, 8.f);
|
||||
// TODO(gibbed): disable imgui.ini saving for now,
|
||||
// imgui assumes paths are char* so we can't throw a good path at it on
|
||||
// Windows.
|
||||
io.IniFilename = nullptr;
|
||||
|
||||
ImFontConfig font_config;
|
||||
font_config.OversampleH = font_config.OversampleV = 2;
|
||||
font_config.PixelSnapH = true;
|
||||
|
||||
LoadCustomFont(io, font_config, font_size);
|
||||
// Failed to load custom font. Trying to load one of OS fonts.
|
||||
if (io.Fonts->Fonts.empty()) {
|
||||
LoadSystemFont(io, font_config, font_size);
|
||||
}
|
||||
// Failed to load OS font. Loading Xenia embedded font.
|
||||
if (io.Fonts->Fonts.empty()) {
|
||||
io.Fonts->AddFontFromMemoryCompressedBase85TTF(
|
||||
kProggyTinyCompressedDataBase85, font_size, &font_config,
|
||||
io.Fonts->GetGlyphRangesDefault());
|
||||
}
|
||||
|
||||
LoadJapaneseFont(io, font_size);
|
||||
}
|
||||
|
||||
void ImGuiDrawer::SetupFontTexture() {
|
||||
if (font_texture_ || !immediate_drawer_) {
|
||||
return;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include "third_party/imgui/imgui.h"
|
||||
#include "xenia/ui/immediate_drawer.h"
|
||||
#include "xenia/ui/presenter.h"
|
||||
#include "xenia/ui/window.h"
|
||||
|
@ -66,6 +67,12 @@ class ImGuiDrawer : public WindowInputListener, public UIDrawer {
|
|||
|
||||
private:
|
||||
void Initialize();
|
||||
void InitializeFonts();
|
||||
void LoadCustomFont(ImGuiIO& io, ImFontConfig& font_config,
|
||||
const float font_size);
|
||||
void LoadSystemFont(ImGuiIO& io, ImFontConfig& font_config,
|
||||
const float font_size);
|
||||
void LoadJapaneseFont(ImGuiIO& io, const float font_size);
|
||||
|
||||
void SetupFontTexture();
|
||||
|
||||
|
|
Loading…
Reference in New Issue