I have set of libraries: fontconfig, freetype, harfbuzz. Is it possible to get scripts list supported by the font?
The task is to create a map of fonts for different unicode scripts.
HarfBuzz, for example, has enum that contains scripts. But I don't understand, is it possible to extract this info from hb_font_t
or hb_face_t
.
Or maybe it's possible to get this info from fontconfig or freetype?
It's possible, but is't very comfortable. I have found this solution:
#include <hb.h>
#include <magic-deps.h>
struct TInstalledFont {
std::string FilePath{};
int FaceIndex{};
std::shared_ptr<hb_face_t> HbFontFace{nullptr};
std::unordered_set<char32_t> Unicodes{};
std::unordered_set<int> HbScripts{};
};
const auto hbUniFuncs = hb_unicode_funcs_get_default();
for (TInstalledFont& font : Fonts) {
auto blob = hb_blob_create_from_file(font.FilePath.c_str());
if (!blob) {
throw std::runtime_error("Failed to load font");
}
DEFER(&blob) {
hb_blob_destroy(blob);
};
const auto face = hb_face_create(blob, font.FaceIndex);
if (!face) {
throw std::runtime_error("Failed to load face");
}
hb_face_make_immutable(face);
font.HbFontFace = std::shared_ptr<hb_face_t>(face, hb_face_destroy);
auto unicodes = hb_set_create();
DEFER(&unicodes) {
hb_set_destroy(unicodes);
};
hb_face_collect_unicodes(face, unicodes);
hb_codepoint_t val{};
while (hb_set_next(unicodes, &val)) {
font.Unicodes.insert(val);
const hb_script_t tagScript = hb_unicode_script(hbUniFuncs, val);
// int because hb_script_t doesn't support hashing
font.HbScripts.insert(static_cast<int>(tagScript));
}
}