7#if defined(MAYAFLUX_PLATFORM_LINUX)
8#include <fontconfig/fontconfig.h>
13#if defined(MAYAFLUX_PLATFORM_LINUX)
15std::optional<std::string>
find_font(std::string_view family, std::string_view style)
17 FcConfig* cfg = FcInitLoadConfigAndFonts();
23 FcPattern* pat = FcNameParse(
24 reinterpret_cast<const FcChar8*
>(std::string(family).c_str()));
26 FcPatternAddString(pat, FC_STYLE,
27 reinterpret_cast<const FcChar8*
>(std::string(style).c_str()));
29 FcConfigSubstitute(cfg, pat, FcMatchPattern);
30 FcDefaultSubstitute(pat);
33 FcPattern* match = FcFontMatch(cfg, pat, &result);
35 std::optional<std::string>
out;
37 FcChar8* file_path {};
38 if (FcPatternGetString(match, FC_FILE, 0, &file_path) == FcResultMatch) {
39 out =
reinterpret_cast<const char*
>(file_path);
42 FcPatternDestroy(match);
47 FcPatternDestroy(pat);
52#elif defined(MAYAFLUX_PLATFORM_MACOS)
54namespace fs = std::filesystem;
56std::optional<std::string>
find_font(std::string_view family, std::string_view style)
58 std::string query = std::string(family);
60 query +=
":style=" + std::string(style);
63 const std::string
cmd =
"fc-match --format='%{file}' '" + query +
"' 2>/dev/null";
67 if (!result.empty() && fs::exists(result)) {
72 const std::vector<fs::path> search_dirs = {
75 "/System/Library/Fonts",
76 "/System/Library/Fonts/Supplemental"
79 std::string lower_family(family);
80 std::ranges::transform(lower_family,
81 lower_family.begin(), [](
unsigned char c) { return std::tolower(c); });
82 std::erase_if(lower_family,
83 [](
unsigned char c) {
return std::isspace(c); });
85 for (
const auto& dir : search_dirs) {
86 if (!fs::exists(dir)) {
89 for (
const auto& entry : fs::directory_iterator(dir)) {
90 const std::string ext = entry.path().extension().string();
91 if (ext !=
".ttf" && ext !=
".otf" && ext !=
".ttc" && ext !=
".otc" && ext !=
".dfont") {
94 std::string lower_name = entry.path().filename().string();
95 std::ranges::transform(lower_name,
96 lower_name.begin(), [](
unsigned char c) { return std::tolower(c); });
97 std::erase_if(lower_name,
98 [](
unsigned char c) {
return std::isspace(c); });
99 if (lower_name.find(lower_family) != std::string::npos) {
101 return entry.path().string();
110#elif defined(MAYAFLUX_PLATFORM_WINDOWS)
114namespace fs = std::filesystem;
116std::optional<std::string>
find_font(std::string_view family, std::string_view )
118 char windir[MAX_PATH] {};
119 GetWindowsDirectoryA(windir, MAX_PATH);
120 const fs::path fonts_dir = fs::path(windir) /
"Fonts";
122 if (!fs::exists(fonts_dir)) {
127 std::string lower_family(family);
128 std::ranges::transform(lower_family, lower_family.begin(),
129 [](
unsigned char c) { return std::tolower(c); });
130 std::erase_if(lower_family,
131 [](
unsigned char c) {
return std::isspace(c); });
133 for (
const auto& entry : fs::directory_iterator(fonts_dir)) {
134 const std::string ext = entry.path().extension().string();
135 if (ext !=
".ttf" && ext !=
".otf") {
138 std::string lower_name = entry.path().filename().string();
139 std::ranges::transform(lower_name, lower_name.begin(),
140 [](
unsigned char c) { return std::tolower(c); });
141 if (lower_name.find(lower_family) != std::string::npos) {
143 return entry.path().string();
#define MF_WARN(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
std::vector< float > * out
@ Init
Engine/subsystem initialization.
@ Portal
High-level user-facing API layer.
MAYAFLUX_API std::optional< std::string > find_font(std::string_view family, std::string_view style={})
Locate a system font file by family name and optional style.