9#include "absl/status/status.h"
10#include "absl/strings/str_cat.h"
11#include "absl/strings/str_format.h"
13#include "imgui/imgui.h"
20static const char* KARLA_REGULAR =
"Karla-Regular.ttf";
21static const char* ROBOTO_MEDIUM =
"Roboto-Medium.ttf";
22static const char* COUSINE_REGULAR =
"Cousine-Regular.ttf";
23static const char* DROID_SANS =
"DroidSans.ttf";
24static const char* NOTO_SANS_JP =
"NotoSansJP.ttf";
25static const char* IBM_PLEX_JP =
"IBMPlexSansJP-Bold.ttf";
27static const float FONT_SIZE_DEFAULT = 16.0F;
28static const float FONT_SIZE_DROID_SANS = 18.0F;
29static const float ICON_FONT_SIZE = 18.0F;
39 return found->string();
42 const std::vector<std::filesystem::path> candidates = {
43 std::filesystem::path(
"assets/font") / font_path,
44 std::filesystem::path(
"../assets/font") / font_path,
45 std::filesystem::path(
"../../assets/font") / font_path,
46 std::filesystem::path(
"../../../assets/font") / font_path,
48 for (
const auto& candidate : candidates) {
49 if (std::filesystem::exists(candidate)) {
50 return candidate.string();
53 return (std::filesystem::path(
"assets/font") / font_path).
string();
60 std::string bundle_path =
61 absl::StrCat(bundle_root,
"assets/font/", font_path);
62 if (std::filesystem::exists(bundle_path)) {
65 bundle_path = absl::StrCat(bundle_root, font_path);
66 if (std::filesystem::exists(bundle_path)) {
72 "Contents/Resources/font/", font_path);
73 if (std::filesystem::exists(bundle_path)) {
84 ImGuiIO& imgui_io = ImGui::GetIO();
88 if (!std::filesystem::exists(actual_font_path)) {
89 return absl::InternalError(
90 absl::StrFormat(
"Font file %s does not exist", actual_font_path));
93 if (!imgui_io.Fonts->AddFontFromFileTTF(actual_font_path.data(),
95 return absl::InternalError(
96 absl::StrFormat(
"Failed to load font from %s", actual_font_path));
98 return absl::OkStatus();
102 static const ImWchar icons_ranges[] = {
ICON_MIN_MD, 0xf900, 0};
103 ImFontConfig icons_config{};
104 icons_config.MergeMode =
true;
105 icons_config.GlyphOffset.y = 5.0F;
106 icons_config.GlyphMinAdvanceX = 13.0F;
107 icons_config.PixelSnapH =
true;
109 ImGuiIO& imgui_io = ImGui::GetIO();
110 if (!imgui_io.Fonts->AddFontFromFileTTF(icon_font_path.c_str(),
111 ICON_FONT_SIZE, &icons_config,
113 return absl::InternalError(
"Failed to add icon fonts");
115 return absl::OkStatus();
123 static std::vector<char>* data = [] {
124 auto* buffer =
new std::vector<char>();
126 std::ios::binary | std::ios::ate);
130 const std::streamsize size = file.tellg();
134 buffer->resize(
static_cast<size_t>(size));
136 if (!file.read(buffer->data(), size)) {
146 if (font_data->empty()) {
147 return absl::InternalError(
"Failed to add Japanese fonts");
149 ImFontConfig japanese_font_config{};
150 japanese_font_config.FontDataOwnedByAtlas =
false;
151 japanese_font_config.MergeMode =
true;
152 japanese_font_config.GlyphOffset.y = 5.0F;
153 japanese_font_config.GlyphMinAdvanceX = 13.0F;
154 japanese_font_config.PixelSnapH =
true;
155 std::strncpy(japanese_font_config.Name, NOTO_SANS_JP,
156 sizeof(japanese_font_config.Name) - 1);
157 ImGuiIO& imgui_io = ImGui::GetIO();
158 if (!imgui_io.Fonts->AddFontFromMemoryTTF(
159 font_data->data(),
static_cast<int>(font_data->size()),
160 ICON_FONT_SIZE, &japanese_font_config,
161 imgui_io.Fonts->GetGlyphRangesJapanese())) {
162 return absl::InternalError(
"Failed to add Japanese fonts");
164 return absl::OkStatus();
174 FontConfig{KARLA_REGULAR, FONT_SIZE_DEFAULT, {}, {}},
175 FontConfig{ROBOTO_MEDIUM, FONT_SIZE_DEFAULT, {}, {}},
176 FontConfig{COUSINE_REGULAR, FONT_SIZE_DEFAULT, {}, {}},
177 FontConfig{IBM_PLEX_JP, FONT_SIZE_DEFAULT, {}, {}},
178 FontConfig{DROID_SANS, FONT_SIZE_DROID_SANS, {}, {}},
188 return absl::OkStatus();
192 ImGuiIO& io = ImGui::GetIO();
193 if (io.Fonts ==
nullptr || io.Fonts->Fonts.Size == 0) {
196 if (index < 0 || index >= io.Fonts->Fonts.Size) {
199 io.FontDefault = io.Fonts->Fonts[index];
203 ImGuiIO& imgui_io = ImGui::GetIO();
204 std::string actual_font_path = SetFontPath(config.
font_path);
205 if (!imgui_io.Fonts->AddFontFromFileTTF(actual_font_path.data(),
207 return absl::InternalError(
208 absl::StrFormat(
"Failed to load font from %s", actual_font_path));
212 return absl::OkStatus();
216 const std::string& data,
float size_pixels) {
217 ImGuiIO& imgui_io = ImGui::GetIO();
220 void* font_data = ImGui::MemAlloc(data.size());
222 return absl::InternalError(
"Failed to allocate memory for font data");
224 std::memcpy(font_data, data.data(), data.size());
227 std::strncpy(config.Name, name.c_str(),
sizeof(config.Name) - 1);
228 config.Name[
sizeof(config.Name) - 1] = 0;
230 if (!imgui_io.Fonts->AddFontFromMemoryTTF(
231 font_data,
static_cast<int>(data.size()), size_pixels, &config)) {
232 ImGui::MemFree(font_data);
233 return absl::InternalError(
"Failed to load font from memory");
247 return absl::OkStatus();
#define FONT_ICON_FILE_NAME_MD
absl::Status AddJapaneseFont(const FontConfig &)
std::string ResolveRepoFontPath(const std::string &font_path)
std::vector< char > * JapaneseFontData()
std::string SetFontPath(const std::string &font_path)
absl::Status LoadFont(const FontConfig &font_config)
absl::Status AddIconFont(const FontConfig &)
std::string GetBundleResourcePath()
GetBundleResourcePath returns the path to the bundle resource directory. Specific to MacOS.
absl::Status ReloadPackageFont(const FontConfig &config)
absl::Status LoadPackageFonts()
absl::Status LoadFontFromMemory(const std::string &name, const std::string &data, float size_pixels)
void SetActiveFontIndex(int index)
#define RETURN_IF_ERROR(expr)
std::vector< FontConfig > fonts