X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Ffont_config.cc;h=8804bd6d96522b8aa2baf0a8b9e341405393766e;hb=8b52763e14ae99c0b04d381afdea0aa915c1c56d;hp=c7361bc04823e7547a74b5117c5dfdbd732bd252;hpb=9a7b67aee32a40539f29bc2d7017edd4a4f65f11;p=dcpomatic.git diff --git a/src/lib/font_config.cc b/src/lib/font_config.cc index c7361bc04..8804bd6d9 100644 --- a/src/lib/font_config.cc +++ b/src/lib/font_config.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2014-2021 Carl Hetherington + Copyright (C) 2014-2023 Carl Hetherington This file is part of DCP-o-matic. @@ -20,11 +20,16 @@ #include "dcpomatic_assert.h" +#include "dcpomatic_log.h" +#include "font.h" #include "font_config.h" +#include "util.h" #include +#include #include +using std::shared_ptr; using std::string; using boost::optional; @@ -39,14 +44,38 @@ FontConfig::FontConfig() } +FontConfig::~FontConfig() +{ + for (auto file: _temp_files) { + boost::system::error_code ec; + boost::filesystem::remove(file, ec); + } +} + + string -FontConfig::make_font_available(boost::filesystem::path font_file) +FontConfig::make_font_available(shared_ptr font) { - auto existing = _available_fonts.find(font_file); + auto existing = _available_fonts.find(font->content()); if (existing != _available_fonts.end()) { return existing->second; } + boost::filesystem::path font_file = default_font_file(); + if (font->file()) { + font_file = *font->file(); + } else if (font->data()) { + /* This font only exists in memory (so far) but FontConfig doesn't have an API to add a font + * from a memory buffer (AFAICS). + * https://gitlab.freedesktop.org/fontconfig/fontconfig/-/issues/12 + * As a workaround, write the font data to a temporary file and use that. + */ + font_file = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); + _temp_files.push_back(font_file); + font->data()->write(font_file); + } + + /* Make this font available to DCP-o-matic */ optional font_name; FcConfigAppFontAddFile (_config, reinterpret_cast(font_file.string().c_str())); @@ -78,13 +107,54 @@ FontConfig::make_font_available(boost::filesystem::path font_file) DCPOMATIC_ASSERT(font_name); - _available_fonts[font_file] = *font_name; + /* We need to use the font object as the key, as we may be passed the same shared_ptr to a modified + * Font object in the future and in that case we need to load the new font. + */ + _available_fonts[font->content()] = *font_name; FcConfigBuildFonts(_config); return *font_name; } +optional +FontConfig::system_font_with_name(string name) +{ + optional path; + + LOG_GENERAL("Searching system for font %1", name); + auto pattern = FcNameParse(reinterpret_cast(name.c_str())); + auto object_set = FcObjectSetBuild(FC_FILE, nullptr); + auto font_set = FcFontList(_config, pattern, object_set); + if (font_set) { + LOG_GENERAL("%1 candidate fonts found", font_set->nfont); + for (int i = 0; i < font_set->nfont; ++i) { + auto font = font_set->fonts[i]; + FcChar8* file; + if (FcPatternGetString(font, FC_FILE, 0, &file) == FcResultMatch) { + path = boost::filesystem::path(reinterpret_cast(file)); + LOG_GENERAL("Found %1", *path); + break; + } + } + FcFontSetDestroy(font_set); + } else { + LOG_GENERAL_NC("No candidate fonts found"); + } + + FcObjectSetDestroy(object_set); + FcPatternDestroy(pattern); + + if (path) { + LOG_GENERAL("Searched system for font %1, found %2", name, *path); + } else { + LOG_GENERAL("Searched system for font %1; nothing found", name); + } + + return path; +} + + FontConfig * FontConfig::instance() { @@ -95,3 +165,11 @@ FontConfig::instance() return _instance; } + +void +FontConfig::drop() +{ + delete _instance; + _instance = nullptr; +} +