Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[UI] Changed default Windows font & Allow loading custom font #2135

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/xenia/base/system.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_
4 changes: 4 additions & 0 deletions src/xenia/base/system_android.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 4 additions & 0 deletions src/xenia/base/system_gnulinux.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
23 changes: 23 additions & 0 deletions src/xenia/base/system_win.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
******************************************************************************
*/

#include <ShlObj_core.h>

#include "xenia/base/platform_win.h"
#include "xenia/base/string.h"
#include "xenia/base/system.h"
Expand Down Expand Up @@ -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
138 changes: 106 additions & 32 deletions src/xenia/ui/imgui_drawer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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 {

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
7 changes: 7 additions & 0 deletions src/xenia/ui/imgui_drawer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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();

Expand Down