105 lines
2.2 KiB
C++
105 lines
2.2 KiB
C++
|
|
#include "TextRenderer.hpp"
|
||
|
|
|
||
|
|
#include <cassert>
|
||
|
|
#include <cstdlib>
|
||
|
|
#include <mutex>
|
||
|
|
#include <optional>
|
||
|
|
#include <string>
|
||
|
|
#include <string_view>
|
||
|
|
#include <unordered_map>
|
||
|
|
|
||
|
|
#include <fontconfig/fontconfig.h>
|
||
|
|
|
||
|
|
#include <raylib.h>
|
||
|
|
|
||
|
|
TextRenderer::TextRenderer()
|
||
|
|
{
|
||
|
|
static char const msdf_fs_data[] {
|
||
|
|
#embed "msdf.fs"
|
||
|
|
, 0
|
||
|
|
};
|
||
|
|
m_msdf_shader = LoadShaderFromMemory(nullptr, msdf_fs_data);
|
||
|
|
assert(IsShaderValid(m_msdf_shader));
|
||
|
|
}
|
||
|
|
|
||
|
|
TextRenderer::~TextRenderer() { UnloadShader(m_msdf_shader); }
|
||
|
|
|
||
|
|
auto TextRenderer::measure_text(FontHandle const font,
|
||
|
|
std::string_view const text, int const size) -> Vector2
|
||
|
|
{
|
||
|
|
// FIXME: Implement.
|
||
|
|
return {};
|
||
|
|
}
|
||
|
|
|
||
|
|
auto TextRenderer::draw_text(FontHandle const font, std::string_view const text,
|
||
|
|
Vector2 const pos, int const size, Color const color) -> void
|
||
|
|
{
|
||
|
|
int const pos_x = pos.x;
|
||
|
|
int const pos_y = pos.y;
|
||
|
|
// Don't use pos from here on out!
|
||
|
|
// FIXME: Implement.
|
||
|
|
(void)pos_x, (void)pos_y;
|
||
|
|
}
|
||
|
|
|
||
|
|
auto TextRenderer::load_font(std::filesystem::path const &path)
|
||
|
|
-> std::optional<FontHandle>
|
||
|
|
{
|
||
|
|
// FIXME: Implement.
|
||
|
|
return std::nullopt;
|
||
|
|
}
|
||
|
|
|
||
|
|
auto TextRenderer::unload_font(FontHandle const font)
|
||
|
|
{
|
||
|
|
// FIXME: Implement.
|
||
|
|
}
|
||
|
|
|
||
|
|
auto find_font_path(std::string_view path)
|
||
|
|
-> std::optional<std::filesystem::path>
|
||
|
|
{
|
||
|
|
static std::once_flag fc_once;
|
||
|
|
std::call_once(fc_once, []() {
|
||
|
|
if (FcInit())
|
||
|
|
std::atexit([] { FcFini(); });
|
||
|
|
});
|
||
|
|
|
||
|
|
static std::mutex m;
|
||
|
|
static std::unordered_map<std::string, std::optional<std::string>> cache;
|
||
|
|
|
||
|
|
std::string const key(path);
|
||
|
|
|
||
|
|
{
|
||
|
|
std::scoped_lock lock(m);
|
||
|
|
if (auto it = cache.find(key); it != cache.end())
|
||
|
|
return it->second;
|
||
|
|
}
|
||
|
|
|
||
|
|
FcPattern *pattern
|
||
|
|
= FcNameParse(reinterpret_cast<FcChar8 const *>(key.c_str()));
|
||
|
|
if (!pattern) {
|
||
|
|
std::scoped_lock lock(m);
|
||
|
|
return cache[key] = std::nullopt;
|
||
|
|
}
|
||
|
|
|
||
|
|
FcConfigSubstitute(nullptr, pattern, FcMatchPattern);
|
||
|
|
FcDefaultSubstitute(pattern);
|
||
|
|
|
||
|
|
FcResult result;
|
||
|
|
FcPattern *font = FcFontMatch(nullptr, pattern, &result);
|
||
|
|
|
||
|
|
std::optional<std::string> final_path;
|
||
|
|
if (font) {
|
||
|
|
FcChar8 *file;
|
||
|
|
if (FcPatternGetString(font, FC_FILE, 0, &file) == FcResultMatch)
|
||
|
|
final_path = reinterpret_cast<char *>(file);
|
||
|
|
FcPatternDestroy(font);
|
||
|
|
}
|
||
|
|
|
||
|
|
FcPatternDestroy(pattern);
|
||
|
|
|
||
|
|
{
|
||
|
|
std::scoped_lock lock(m);
|
||
|
|
cache[key] = final_path;
|
||
|
|
}
|
||
|
|
return final_path;
|
||
|
|
}
|