5#include "fifechan/fontloader.hpp"
17#include "fifechan/exception.hpp"
33 std::filesystem::path getExecutablePath()
36 wchar_t path[MAX_PATH];
37 GetModuleFileNameW(
nullptr, path, MAX_PATH);
38 return std::filesystem::path(path);
40 std::array<char, PATH_MAX> path{};
41 ssize_t
const len = readlink(
"/proc/self/exe", path.data(), path.size() - 1);
43 path.at(
static_cast<size_t>(len)) =
'\0';
50 std::vector<std::filesystem::path> getSystemFontPaths()
52 std::vector<std::filesystem::path> paths;
55 wchar_t const * winDir = _wgetenv(L
"WINDIR");
57 paths.emplace_back(std::filesystem::path(winDir) / L
"Fonts");
59 paths.emplace_back(L
"C:\\Windows\\Fonts");
63 paths.emplace_back(
"/usr/share/fonts");
64 paths.emplace_back(
"/usr/local/share/fonts");
65 paths.emplace_back(std::filesystem::path(getenv(
"HOME")) /
".local/share/fonts");
66 paths.emplace_back(std::filesystem::path(getenv(
"HOME")) /
".fonts");
71 std::vector<std::string> getFontExtensions()
73 return {
".ttf",
".otf",
".TTF",
".OTF",
".woff",
".WOFF"};
80 std::vector<std::filesystem::path> paths;
83 paths.emplace_back(std::filesystem::current_path());
86 auto exePath = getExecutablePath();
87 if (!exePath.empty()) {
88 paths.push_back(exePath.parent_path());
92 auto systemPaths = getSystemFontPaths();
93 paths.insert(paths.end(), systemPaths.begin(), systemPaths.end());
96 paths.emplace_back(
"tests/resources");
97 paths.emplace_back(
"../tests/resources");
98 paths.emplace_back(
"./tests/resources");
101 std::vector<std::filesystem::path> uniquePaths;
102 std::ranges::copy_if(
105 std::back_inserter(uniquePaths),
106 [&uniquePaths](std::filesystem::path
const & p) {
107 return std::ranges::find(uniquePaths, p) == uniquePaths.end();
114 std::string
const & fontName, std::vector<std::filesystem::path>
const & searchPaths)
120 std::filesystem::path
const fontPath(fontName);
121 bool const hasExtension = fontPath.has_extension();
123 auto extensions = getFontExtensions();
125 for (
auto const & dir : paths) {
128 std::filesystem::path fullPath = dir / fontName;
129 if (std::filesystem::exists(fullPath)) {
134 for (
auto const & ext : extensions) {
135 std::filesystem::path fullPath = dir / (fontName + ext);
136 if (std::filesystem::exists(fullPath)) {
148 std::string
const & fontName,
150 std::vector<std::filesystem::path>
const & searchPaths)
154 if (fontFile.empty()) {
155 throw fcn::Exception(
"loadFont: Could not find font '" + fontName +
"'");
158 auto font = graphics.
createFont(fontFile.string(), size);
160 throw fcn::Exception(
"loadFont: Failed to load font from '" + fontFile.string() +
"'");
An exception class containing a message, a file, and a line number where the exception occurred.
Abstract interface providing primitive drawing functions (lines, rectangles, etc.).
virtual std::shared_ptr< Font > createFont(std::string const &filename, int size)
Creates a font for this graphics backend.
static std::filesystem::path findFontFile(std::string const &fontName, std::vector< std::filesystem::path > const &searchPaths={})
Find a font file by name searching the provided paths.
static std::vector< std::filesystem::path > getDefaultSearchPaths()
Returns default search paths used when locating font files on the current platform.
static std::shared_ptr< Font > loadFont(Graphics &graphics, std::string const &fontName, int size, std::vector< std::filesystem::path > const &searchPaths={})
Load a Font object for the given font name and size using the provided Graphics implementation.