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() {
65 ImGuiIO& io = ImGui::GetIO();
66 static const ImWchar icons_ranges[] = {ICON_MIN_MD, 0xf900, 0};
67 ImFontConfig icons_config;
68 icons_config.MergeMode = true;
69 icons_config.GlyphOffset.y = 5.0f;
70 icons_config.GlyphMinAdvanceX = 13.0f;
71 icons_config.PixelSnapH = true;
72 std::string icon_font_path = SetFontPath(FONT_ICON_FILE_NAME_MD);
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() {
81 ImGuiIO& io = ImGui::GetIO();
82 ImFontConfig japanese_font_config;
83 japanese_font_config.MergeMode = true;
84 japanese_font_config.GlyphOffset.y = 5.0f;
85 japanese_font_config.GlyphMinAdvanceX = 13.0f;
86 japanese_font_config.PixelSnapH = true;
87 std::string japanese_font_path = SetFontPath(NOTO_SANS_JP);
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 ImGuiIO& io = ImGui::GetIO();
100
101 // Icon configuration
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;
108
109 // Japanese font configuration
110 ImFontConfig japanese_font_config;
111 japanese_font_config.MergeMode = true;
112 icons_config.GlyphOffset.y = 5.0f;
113 icons_config.GlyphMinAdvanceX = 13.0f;
114 icons_config.PixelSnapH = true;
115
116 // List of fonts to be loaded
117 std::vector<const char*> font_paths = {
118 KARLA_REGULAR, ROBOTO_MEDIUM, COUSINE_REGULAR, IBM_PLEX_JP, DROID_SANS};
119
120 // Load fonts with associated icon and Japanese merges
121 for (const auto& font_path : font_paths) {
122 float font_size =
123 (font_path == DROID_SANS) ? FONT_SIZE_DROID_SANS : FONT_SIZE_DEFAULT;
124
125 FontConfig font_config = {font_path, font_size};
126 RETURN_IF_ERROR(LoadFont(font_config));
127
128 // Merge icon set
129 RETURN_IF_ERROR(AddIconFont());
130
131 // Merge Japanese font
132 RETURN_IF_ERROR(AddJapaneseFont());
133 }
134 return absl::OkStatus();
135}
136
137absl::Status ReloadPackageFont(const FontConfig& config) {
138 ImGuiIO& io = ImGui::GetIO();
139 std::string actual_font_path = SetFontPath(config.font_path);
140 if (!io.Fonts->AddFontFromFileTTF(actual_font_path.data(),
141 config.font_size)) {
142 return absl::InternalError(
143 absl::StrFormat("Failed to load font from %s", actual_font_path));
144 }
145 RETURN_IF_ERROR(AddIconFont());
146 RETURN_IF_ERROR(AddJapaneseFont());
147 return absl::OkStatus();
148}
149
150#ifdef _WIN32
151#include <Windows.h>
152
153int CALLBACK EnumFontFamExProc(const LOGFONT* lpelfe, const TEXTMETRIC* lpntme,
154 DWORD FontType, LPARAM lParam) {
155 // Step 3: Load the font into ImGui
156 ImGuiIO& io = ImGui::GetIO();
157 io.Fonts->AddFontFromFileTTF(lpelfe->lfFaceName, 16.0f);
158
159 return 1;
160}
161
162void LoadSystemFonts() {
163 HKEY hKey;
164 std::vector<std::string> fontPaths;
165
166 // Open the registry key where fonts are listed
167 if (RegOpenKeyEx(
168 HKEY_LOCAL_MACHINE,
169 TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"), 0,
170 KEY_READ, &hKey) == ERROR_SUCCESS) {
171 DWORD valueCount;
172 DWORD maxValueNameSize;
173 DWORD maxValueDataSize;
174
175 // Query the number of entries and the maximum size of the names and values
176 RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL, &valueCount,
177 &maxValueNameSize, &maxValueDataSize, NULL, NULL);
178
179 char* valueName = new char[maxValueNameSize + 1]; // +1 for null terminator
180 BYTE* valueData = new BYTE[maxValueDataSize + 1]; // +1 for null terminator
181
182 // Enumerate all font entries
183 for (DWORD i = 0; i < valueCount; i++) {
184 DWORD valueNameSize = maxValueNameSize + 1; // +1 for null terminator
185 DWORD valueDataSize = maxValueDataSize + 1; // +1 for null terminator
186 DWORD valueType;
187
188 // Clear buffers
189 memset(valueName, 0, valueNameSize);
190 memset(valueData, 0, valueDataSize);
191
192 // Get the font name and file path
193 if (RegEnumValue(hKey, i, valueName, &valueNameSize, NULL, &valueType,
194 valueData, &valueDataSize) == ERROR_SUCCESS) {
195 if (valueType == REG_SZ) {
196 // Add the font file path to the vector
197 std::string fontPath(reinterpret_cast<char*>(valueData),
198 valueDataSize);
199
200 fontPaths.push_back(fontPath);
201 }
202 }
203 }
204
205 delete[] valueName;
206 delete[] valueData;
207
208 RegCloseKey(hKey);
209 }
210
211 ImGuiIO& io = ImGui::GetIO();
212
213 // List of common font face names
214 static const std::unordered_set<std::string> commonFontFaceNames = {
215 "arial",
216 "times",
217 "cour",
218 "verdana",
219 "tahoma",
220 "comic",
221 "Impact",
222 "ariblk",
223 "Trebuchet MS",
224 "Georgia",
225 "Palatino Linotype",
226 "Lucida Sans Unicode",
227 "Tahoma",
228 "Lucida Console"};
229
230 for (auto& fontPath : fontPaths) {
231 // Check if the font path has a "C:\" prefix
232 if (fontPath.substr(0, 2) != "C:") {
233 // Add "C:\Windows\Fonts\" prefix to the font path
234 fontPath = absl::StrFormat("C:\\Windows\\Fonts\\%s", fontPath.c_str());
235 }
236
237 // Check if the font file has a .ttf or .TTF extension
238 std::string extension = fontPath.substr(fontPath.find_last_of(".") + 1);
239 if (extension == "ttf" || extension == "TTF") {
240 // Get the font face name from the font path
241 std::string fontFaceName =
242 fontPath.substr(fontPath.find_last_of("\\/") + 1);
243 fontFaceName = fontFaceName.substr(0, fontFaceName.find_last_of("."));
244
245 // Check if the font face name is in the common font face names list
246 if (commonFontFaceNames.find(fontFaceName) != commonFontFaceNames.end()) {
247 io.Fonts->AddFontFromFileTTF(fontPath.c_str(), 16.0f);
248
249 // Merge icon set
250 // Icon configuration
251 static const ImWchar icons_ranges[] = {ICON_MIN_MD, 0xf900, 0};
252 ImFontConfig icons_config;
253 static const float ICON_FONT_SIZE = 18.0f;
254 icons_config.MergeMode = true;
255 icons_config.GlyphOffset.y = 5.0f;
256 icons_config.GlyphMinAdvanceX = 13.0f;
257 icons_config.PixelSnapH = true;
258 io.Fonts->AddFontFromFileTTF(FONT_ICON_FILE_NAME_MD, ICON_FONT_SIZE,
259 &icons_config, icons_ranges);
260 }
261 }
262 }
263}
264
265#elif defined(__linux__)
266
267void LoadSystemFonts() {
268 // Load Linux System Fonts into ImGui
269}
270
271#endif
272
273} // namespace core
274} // 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:62
std::string SetFontPath(const std::string &font_path)
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:10