From d1a478ad12ffeb2ee2135298c3d4229fc49659f1 Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Sat, 23 Sep 2023 00:44:35 -0500 Subject: [PATCH] Perform font matching from placefile --- .../scwx/qt/manager/placefile_manager.cpp | 32 ++++++++- .../scwx/qt/manager/resource_manager.cpp | 71 +++++++++++++++++++ .../scwx/qt/manager/resource_manager.hpp | 3 + wxdata/include/scwx/gr/placefile.hpp | 3 + 4 files changed, 106 insertions(+), 3 deletions(-) diff --git a/scwx-qt/source/scwx/qt/manager/placefile_manager.cpp b/scwx-qt/source/scwx/qt/manager/placefile_manager.cpp index 77344524..9f10a714 100644 --- a/scwx-qt/source/scwx/qt/manager/placefile_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/placefile_manager.cpp @@ -51,8 +51,10 @@ public: void ReadPlacefileSettings(); void WritePlacefileSettings(); + static void + LoadFontResources(const std::shared_ptr& placefile); static std::vector> - LoadResources(const std::shared_ptr& placefile); + LoadImageResources(const std::shared_ptr& placefile); boost::asio::thread_pool threadPool_ {1u}; @@ -587,7 +589,8 @@ void PlacefileManager::Impl::PlacefileRecord::Update() if (updatedPlacefile != nullptr) { // Load placefile resources - auto newImages = Impl::LoadResources(updatedPlacefile); + Impl::LoadFontResources(updatedPlacefile); + auto newImages = Impl::LoadImageResources(updatedPlacefile); // Check the name matches, in case the name updated if (name_ == name) @@ -684,8 +687,31 @@ std::shared_ptr PlacefileManager::Instance() return placefileManager; } +void PlacefileManager::Impl::LoadFontResources( + const std::shared_ptr& placefile) +{ + auto fonts = placefile->fonts(); + + for (auto& font : fonts) + { + units::font_size::pixels size {font.second->pixels_}; + std::vector styles {}; + + if (font.second->IsBold()) + { + styles.push_back("bold"); + } + if (font.second->IsItalic()) + { + styles.push_back("italic"); + } + + ResourceManager::LoadFontResource(font.second->face_, styles, size); + } +} + std::vector> -PlacefileManager::Impl::LoadResources( +PlacefileManager::Impl::LoadImageResources( const std::shared_ptr& placefile) { const auto iconFiles = placefile->icon_files(); diff --git a/scwx-qt/source/scwx/qt/manager/resource_manager.cpp b/scwx-qt/source/scwx/qt/manager/resource_manager.cpp index 21af6e43..10ad2557 100644 --- a/scwx-qt/source/scwx/qt/manager/resource_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/resource_manager.cpp @@ -34,6 +34,8 @@ static void LoadFcApplicationFont(const std::string& fontFilename); static void LoadFonts(); static void LoadTextures(); +static const std::string kFcTrueType_ {"TrueType"}; + static const std::vector> fontNames_ { {types::Font::din1451alt, ":/res/fonts/din1451alt.ttf"}, {types::Font::din1451alt_g, ":/res/fonts/din1451alt_g.ttf"}, @@ -44,6 +46,9 @@ static std::string fontCachePath_ {}; static std::unordered_map fontIds_ {}; static std::unordered_map> fonts_ {}; +static FcFontSet* fcFontSet_ {nullptr}; +static FcObjectSet* fcObjectSet_ {nullptr}; + void Initialize() { config::CountyDatabase::Initialize(); @@ -80,6 +85,72 @@ std::shared_ptr Font(types::Font font) return nullptr; } +void LoadFontResource(const std::string& family, + const std::vector& styles, + units::font_size::points size) +{ + const std::string styleString = fmt::format("{}", fmt::join(styles, " ")); + const std::string fontString = + fmt::format("{}-{}:{}", family, size.value(), styleString); + + logger_->debug("LoadFontResource: {}", fontString); + + // Build fontconfig pattern + FcPattern* pattern = FcPatternCreate(); + + FcPatternAddString( + pattern, FC_FAMILY, reinterpret_cast(family.c_str())); + FcPatternAddDouble(pattern, FC_SIZE, size.value()); + FcPatternAddString(pattern, + FC_FONTFORMAT, + reinterpret_cast(kFcTrueType_.c_str())); + + if (!styles.empty()) + { + FcPatternAddString(pattern, + FC_STYLE, + reinterpret_cast(styleString.c_str())); + } + + // Perform font pattern match substitution + FcConfigSubstitute(nullptr, pattern, FcMatchPattern); + FcDefaultSubstitute(pattern); + + // Find matching font + FcResult result; + FcPattern* match = FcFontMatch(nullptr, pattern, &result); + std::string fontFile {}; + + if (match != nullptr) + { + FcChar8* fcFamily; + FcChar8* fcStyle; + FcChar8* fcFile; + + // Match was found, get properties + if (FcPatternGetString(match, FC_FAMILY, 0, &fcFamily) == FcResultMatch && + FcPatternGetString(match, FC_STYLE, 0, &fcStyle) == FcResultMatch && + FcPatternGetString(match, FC_FILE, 0, &fcFile) == FcResultMatch) + { + fontFile = reinterpret_cast(fcFile); + + logger_->debug("Found matching font: {}:{} ({})", + reinterpret_cast(fcFamily), + reinterpret_cast(fcStyle), + fontFile); + } + } + + if (fontFile.empty()) + { + logger_->warn("Could not find matching font: {}", fontString); + } + + // Cleanup + FcPatternDestroy(match); + FcPatternDestroy(pattern); +} + std::shared_ptr LoadImageResource(const std::string& urlString) { diff --git a/scwx-qt/source/scwx/qt/manager/resource_manager.hpp b/scwx-qt/source/scwx/qt/manager/resource_manager.hpp index 7b8003c9..45115fd7 100644 --- a/scwx-qt/source/scwx/qt/manager/resource_manager.hpp +++ b/scwx-qt/source/scwx/qt/manager/resource_manager.hpp @@ -22,6 +22,9 @@ void Shutdown(); int FontId(types::Font font); std::shared_ptr Font(types::Font font); +void LoadFontResource(const std::string& family, + const std::vector& styles, + units::font_size::points size); std::shared_ptr LoadImageResource(const std::string& urlString); std::vector> diff --git a/wxdata/include/scwx/gr/placefile.hpp b/wxdata/include/scwx/gr/placefile.hpp index 017cc112..e9b381fe 100644 --- a/wxdata/include/scwx/gr/placefile.hpp +++ b/wxdata/include/scwx/gr/placefile.hpp @@ -67,6 +67,9 @@ public: std::size_t pixels_ {}; std::int32_t flags_ {}; std::string face_ {}; + + bool IsBold() { return flags_ & 1; } + bool IsItalic() { return flags_ & 2; } }; struct DrawItem