#include "font_loader.hpp" #include "core/config/config.hpp" #include "imgui_internal.h" #include #include #if defined(_WIN32) #include #include #include static std::string search_registry_for_font(HKEY root_key, const char* subkey, const std::string& font_name_lower, const char* default_font_dir) { HKEY hKey; LONG result = RegOpenKeyExA(root_key, subkey, 0, KEY_READ, &hKey); if (result != ERROR_SUCCESS) return {}; char value_name[512]; BYTE value_data[512]; DWORD value_name_size, value_data_size, type; DWORD index = 0; std::string found_path; while (true) { value_name_size = sizeof(value_name); value_data_size = sizeof(value_data); result = RegEnumValueA(hKey, index++, value_name, &value_name_size, nullptr, &type, value_data, &value_data_size); if (result != ERROR_SUCCESS) break; if (type != REG_SZ) continue; std::string reg_font_name = value_name; std::transform(reg_font_name.begin(), reg_font_name.end(), reg_font_name.begin(), ::tolower); if (reg_font_name.find(font_name_lower) != std::string::npos) { std::string font_file = reinterpret_cast(value_data); // If path is not absolute, prepend default font directory if (font_file.find(":\\") == std::string::npos) { found_path = std::string(default_font_dir) + "\\" + font_file; } else { found_path = font_file; } break; } } RegCloseKey(hKey); return found_path; } std::string font_loader::find_font_windows(const char* font_name) { std::string font_name_lower = font_name; std::transform(font_name_lower.begin(), font_name_lower.end(), font_name_lower.begin(), ::tolower); char windows_dir[MAX_PATH]; GetWindowsDirectoryA(windows_dir, MAX_PATH); std::string system_fonts_dir = std::string(windows_dir) + "\\Fonts"; // First, try system-wide fonts (HKEY_LOCAL_MACHINE) std::string path = search_registry_for_font( HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts", font_name_lower, system_fonts_dir.c_str() ); if (!path.empty()) return path; // If not found, try per-user fonts (HKEY_CURRENT_USER) char local_appdata[MAX_PATH]; if (GetEnvironmentVariableA("LOCALAPPDATA", local_appdata, MAX_PATH) > 0) { std::string user_fonts_dir = std::string(local_appdata) + "\\Microsoft\\Windows\\Fonts"; path = search_registry_for_font( HKEY_CURRENT_USER, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts", font_name_lower, user_fonts_dir.c_str() ); } return path; } #endif #if defined(__APPLE__) #include std::vector font_loader::load_font_macos(const char* font_name) { std::vector out; CFStringRef cf_name = CFStringCreateWithCString(nullptr, font_name, kCFStringEncodingUTF8); if (!cf_name) return out; CTFontDescriptorRef desc = CTFontDescriptorCreateWithNameAndSize(cf_name, 12); CFRelease(cf_name); if (!desc) return out; CTFontRef font = CTFontCreateWithFontDescriptor(desc, 0, nullptr); CFRelease(desc); if (!font) return out; CFDataRef data = CTFontCopyTable(font, kCTFontTableCFF, 0); if (!data) data = CTFontCopyTable(font, kCTFontTableHead, 0); if (data) { CFIndex size = CFDataGetLength(data); out.resize(size); CFDataGetBytes(data, CFRangeMake(0, size), out.data()); CFRelease(data); } CFRelease(font); return out; } #endif #if !defined(_WIN32) && !defined(__APPLE__) #include std::string font_loader::find_font_linux(const char* font_name) { FcInit(); FcPattern* pattern = FcNameParse(reinterpret_cast(font_name)); if (!pattern) return {}; FcConfigSubstitute(nullptr, pattern, FcMatchPattern); FcDefaultSubstitute(pattern); FcResult result; FcPattern* match = FcFontMatch(nullptr, pattern, &result); std::string out; if (match) { FcChar8* file = nullptr; if (FcPatternGetString(match, FC_FILE, 0, &file) == FcResultMatch) out = reinterpret_cast(file); FcPatternDestroy(match); } FcPatternDestroy(pattern); return out; } #endif std::string font_loader::find_font_path(const char* font_name) { #if defined(_WIN32) return find_font_windows(font_name); #elif defined(__APPLE__) (void)font_name; return {}; #else return find_font_linux(font_name); #endif } ImFont* font_loader::load_font(const char* font_name, float size_px) { #if defined(__APPLE__) std::vector buf = load_font_macos(font_name); if (buf.empty()) return nullptr; return ImGui::GetIO().Fonts->AddFontFromMemoryTTF( buf.data(), static_cast(buf.size()), size_px ); #else std::string path = find_font_path(font_name); if (path.empty()) return nullptr; float scale = ImGui::GetIO().DisplayFramebufferScale.y; return ImGui::GetIO().Fonts->AddFontFromFileTTF( path.c_str(), size_px * scale ); #endif } void font_loader::push_default_font() { ImGui::PushFont(ImGui::GetDefaultFont(), clrsync::core::config::instance().font_size()); } void font_loader::pop_font() { ImGui::PopFont(); }