yaze 0.2.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
font_loader.cc
Go to the documentation of this file.
2
3#include <filesystem>
4#include <string>
5#include <unordered_set>
6#include <vector>
7
8#include "absl/status/status.h"
9#include "absl/strings/str_cat.h"
10#include "absl/strings/str_format.h"
12#include "app/gui/icons.h"
13#include "imgui/imgui.h"
14#include "util/macro.h"
15
16namespace yaze {
17namespace core {
18
19static const char* KARLA_REGULAR = "Karla-Regular.ttf";
20static const char* ROBOTO_MEDIUM = "Roboto-Medium.ttf";
21static const char* COUSINE_REGULAR = "Cousine-Regular.ttf";
22static const char* DROID_SANS = "DroidSans.ttf";
23static const char* NOTO_SANS_JP = "NotoSansJP.ttf";
24static const char* IBM_PLEX_JP = "IBMPlexSansJP-Bold.ttf";
25
26static const float FONT_SIZE_DEFAULT = 16.0f;
27static const float FONT_SIZE_DROID_SANS = 18.0f;
28static const float ICON_FONT_SIZE = 18.0f;
29
30namespace {
31
32std::string SetFontPath(const std::string& font_path) {
33#ifdef __APPLE__
34#if TARGET_OS_IOS == 1
35 const std::string kBundlePath = GetBundleResourcePath();
36 return kBundlePath + font_path;
37#else
38 return absl::StrCat(GetBundleResourcePath(), "Contents/Resources/font/",
39 font_path);
40#endif
41#else
42 return absl::StrCat("assets/font/", font_path);
43#endif
44}
45
46absl::Status LoadFont(const FontConfig& font_config) {
47 ImGuiIO& io = ImGui::GetIO();
48 std::string actual_font_path = SetFontPath(font_config.font_path);
49 // Check if the file exists with std library first, since ImGui IO will assert
50 // if the file does not exist
51 if (!std::filesystem::exists(actual_font_path)) {
52 return absl::InternalError(
53 absl::StrFormat("Font file %s does not exist", actual_font_path));
54 }
55
56 if (!io.Fonts->AddFontFromFileTTF(actual_font_path.data(),
57 font_config.font_size)) {
58 return absl::InternalError(
59 absl::StrFormat("Failed to load font from %s", actual_font_path));
60 }
61 return absl::OkStatus();
62}
63
64absl::Status AddIconFont(const FontConfig& config) {
65 static const ImWchar icons_ranges[] = {ICON_MIN_MD, 0xf900, 0};
66 ImFontConfig icons_config;
67 icons_config.MergeMode = true;
68 icons_config.GlyphOffset.y = 5.0f;
69 icons_config.GlyphMinAdvanceX = 13.0f;
70 icons_config.PixelSnapH = true;
71 std::string icon_font_path = SetFontPath(FONT_ICON_FILE_NAME_MD);
72 ImGuiIO& io = ImGui::GetIO();
73 if (!io.Fonts->AddFontFromFileTTF(icon_font_path.c_str(), ICON_FONT_SIZE,
74 &icons_config, icons_ranges)) {
75 return absl::InternalError("Failed to add icon fonts");
76 }
77 return absl::OkStatus();
78}
79
80absl::Status AddJapaneseFont(const FontConfig& config) {
81 ImFontConfig japanese_font_config;
82 japanese_font_config.MergeMode = true;
83 japanese_font_config.GlyphOffset.y = 5.0f;
84 japanese_font_config.GlyphMinAdvanceX = 13.0f;
85 japanese_font_config.PixelSnapH = true;
86 std::string japanese_font_path = SetFontPath(NOTO_SANS_JP);
87 ImGuiIO& io = ImGui::GetIO();
88 if (!io.Fonts->AddFontFromFileTTF(japanese_font_path.data(), ICON_FONT_SIZE,
89 &japanese_font_config,
90 io.Fonts->GetGlyphRangesJapanese())) {
91 return absl::InternalError("Failed to add Japanese fonts");
92 }
93 return absl::OkStatus();
94}
95
96} // namespace
97
98absl::Status LoadPackageFonts() {
99 if (font_registry.fonts.empty()) {
100 // Initialize the font names and sizes
101 font_registry.fonts = {
102 {KARLA_REGULAR, FONT_SIZE_DEFAULT},
103 {ROBOTO_MEDIUM, FONT_SIZE_DEFAULT},
104 {COUSINE_REGULAR, FONT_SIZE_DEFAULT},
105 {IBM_PLEX_JP, FONT_SIZE_DEFAULT},
106 {DROID_SANS, FONT_SIZE_DROID_SANS},
107 };
108 }
109
110 // Load fonts with associated icon and Japanese merges
111 for (const auto& font_config : font_registry.fonts) {
112 RETURN_IF_ERROR(LoadFont(font_config));
113 RETURN_IF_ERROR(AddIconFont(font_config));
114 RETURN_IF_ERROR(AddJapaneseFont(font_config));
115 }
116 return absl::OkStatus();
117}
118
119absl::Status ReloadPackageFont(const FontConfig& config) {
120 ImGuiIO& io = ImGui::GetIO();
121 std::string actual_font_path = SetFontPath(config.font_path);
122 if (!io.Fonts->AddFontFromFileTTF(actual_font_path.data(),
123 config.font_size)) {
124 return absl::InternalError(
125 absl::StrFormat("Failed to load font from %s", actual_font_path));
126 }
127 RETURN_IF_ERROR(AddIconFont(config));
128 RETURN_IF_ERROR(AddJapaneseFont(config));
129 return absl::OkStatus();
130}
131
132#ifdef _WIN32
133#include <Windows.h>
134
135int CALLBACK EnumFontFamExProc(const LOGFONT* lpelfe, const TEXTMETRIC* lpntme,
136 DWORD FontType, LPARAM lParam) {
137 // Step 3: Load the font into ImGui
138 ImGuiIO& io = ImGui::GetIO();
139 io.Fonts->AddFontFromFileTTF(lpelfe->lfFaceName, 16.0f);
140
141 return 1;
142}
143
144void LoadSystemFonts() {
145 HKEY hKey;
146 std::vector<std::string> fontPaths;
147
148 // Open the registry key where fonts are listed
149 if (RegOpenKeyEx(
150 HKEY_LOCAL_MACHINE,
151 TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"), 0,
152 KEY_READ, &hKey) == ERROR_SUCCESS) {
153 DWORD valueCount;
154 DWORD maxValueNameSize;
155 DWORD maxValueDataSize;
156
157 // Query the number of entries and the maximum size of the names and values
158 RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL, &valueCount,
159 &maxValueNameSize, &maxValueDataSize, NULL, NULL);
160
161 char* valueName = new char[maxValueNameSize + 1]; // +1 for null terminator
162 BYTE* valueData = new BYTE[maxValueDataSize + 1]; // +1 for null terminator
163
164 // Enumerate all font entries
165 for (DWORD i = 0; i < valueCount; i++) {
166 DWORD valueNameSize = maxValueNameSize + 1; // +1 for null terminator
167 DWORD valueDataSize = maxValueDataSize + 1; // +1 for null terminator
168 DWORD valueType;
169
170 // Clear buffers
171 memset(valueName, 0, valueNameSize);
172 memset(valueData, 0, valueDataSize);
173
174 // Get the font name and file path
175 if (RegEnumValue(hKey, i, valueName, &valueNameSize, NULL, &valueType,
176 valueData, &valueDataSize) == ERROR_SUCCESS) {
177 if (valueType == REG_SZ) {
178 // Add the font file path to the vector
179 std::string fontPath(reinterpret_cast<char*>(valueData),
180 valueDataSize);
181
182 fontPaths.push_back(fontPath);
183 }
184 }
185 }
186
187 delete[] valueName;
188 delete[] valueData;
189
190 RegCloseKey(hKey);
191 }
192
193 ImGuiIO& io = ImGui::GetIO();
194
195 // List of common font face names
196 static const std::unordered_set<std::string> commonFontFaceNames = {
197 "arial",
198 "times",
199 "cour",
200 "verdana",
201 "tahoma",
202 "comic",
203 "Impact",
204 "ariblk",
205 "Trebuchet MS",
206 "Georgia",
207 "Palatino Linotype",
208 "Lucida Sans Unicode",
209 "Tahoma",
210 "Lucida Console"};
211
212 for (auto& fontPath : fontPaths) {
213 // Check if the font path has a "C:\" prefix
214 if (fontPath.substr(0, 2) != "C:") {
215 // Add "C:\Windows\Fonts\" prefix to the font path
216 fontPath = absl::StrFormat("C:\\Windows\\Fonts\\%s", fontPath.c_str());
217 }
218
219 // Check if the font file has a .ttf or .TTF extension
220 std::string extension = fontPath.substr(fontPath.find_last_of(".") + 1);
221 if (extension == "ttf" || extension == "TTF") {
222 // Get the font face name from the font path
223 std::string fontFaceName =
224 fontPath.substr(fontPath.find_last_of("\\/") + 1);
225 fontFaceName = fontFaceName.substr(0, fontFaceName.find_last_of("."));
226
227 // Check if the font face name is in the common font face names list
228 if (commonFontFaceNames.find(fontFaceName) != commonFontFaceNames.end()) {
229 io.Fonts->AddFontFromFileTTF(fontPath.c_str(), 16.0f);
230
231 // Merge icon set
232 // Icon configuration
233 static const ImWchar icons_ranges[] = {ICON_MIN_MD, 0xf900, 0};
234 ImFontConfig icons_config;
235 static const float ICON_FONT_SIZE = 18.0f;
236 icons_config.MergeMode = true;
237 icons_config.GlyphOffset.y = 5.0f;
238 icons_config.GlyphMinAdvanceX = 13.0f;
239 icons_config.PixelSnapH = true;
240 io.Fonts->AddFontFromFileTTF(FONT_ICON_FILE_NAME_MD, ICON_FONT_SIZE,
241 &icons_config, icons_ranges);
242 }
243 }
244 }
245}
246
247#elif defined(__linux__)
248
249void LoadSystemFonts() {
250 // Load Linux System Fonts into ImGui
251}
252
253#endif
254
255} // namespace core
256} // namespace yaze
#define ICON_MIN_MD
Definition icons.h:8
#define FONT_ICON_FILE_NAME_MD
Definition icons.h:6
#define RETURN_IF_ERROR(expression)
Definition macro.h:51
absl::Status AddIconFont(const FontConfig &config)
std::string SetFontPath(const std::string &font_path)
absl::Status AddJapaneseFont(const FontConfig &config)
absl::Status LoadFont(const FontConfig &font_config)
std::string GetBundleResourcePath()
GetBundleResourcePath returns the path to the bundle resource directory. Specific to MacOS.
absl::Status ReloadPackageFont(const FontConfig &config)
absl::Status LoadPackageFonts()
void LoadSystemFonts()
Main namespace for the application.
Definition controller.cc:18
const char * font_path
Definition font_loader.h:13