From 68c4a396acbe427457701ca6e0ca0878f35b3977 Mon Sep 17 00:00:00 2001 From: Filip Sykala Date: Wed, 13 Oct 2021 11:12:17 +0200 Subject: [PATCH] Second try on linux platform with fontconfig --- src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp | 119 ++++++++++++++++++++++-- 1 file changed, 113 insertions(+), 6 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp index f5c0796c2..28c8c26f2 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp @@ -33,6 +33,10 @@ #define USE_FONT_DIALOG #endif // apple +#ifdef __linux__ +#include +#endif // __linux__ + #ifdef _WIN32 #define USE_FONT_DIALOG #endif // _WIN32 @@ -70,6 +74,102 @@ public: // convert svg image to ExPolygons static ExPolygons to_ExPolygons(NSVGimage *image, float tessTol = 10., int max_level = 10); }; + +#ifdef __linux__ +class FontConfigHelp +{ +public: + FontConfigHelp() { FcInit(); } + ~FontConfigHelp() { FcFini(); } + // inspired by wxpdfdoc - https://github.com/utelle/wxpdfdoc/blob/5bdcdb9953327d06dc50ec312685ccd9bc8400e0/src/pdffontmanager.cpp + std::string get_font_path(const wxFont &font) { + FcConfig *fc = FcInitLoadConfigAndFonts(); + if (fc == nullptr) return ""; + ScopeGuard sg_fc([fc]() { FcConfigDestroy(fc); }); + + wxString fontDesc = font.GetNativeFontInfoUserDesc(); + wxString faceName = font.GetFaceName(); + const wxScopedCharBuffer faceNameBuffer = faceName.ToUTF8(); + const char* fontFamily = faceNameBuffer; + + // Check font slant + int slant = FC_SLANT_ROMAN; + if (fontDesc.Find(wxS("Oblique")) != wxNOT_FOUND) slant = FC_SLANT_OBLIQUE; + else if (fontDesc.Find(wxS("Italic")) != wxNOT_FOUND) slant = FC_SLANT_ITALIC; + + // Check font weight + int weight = FC_WEIGHT_NORMAL; + if (fontDesc.Find(wxS("Book")) != wxNOT_FOUND) weight = FC_WEIGHT_BOOK; + else if (fontDesc.Find(wxS("Medium")) != wxNOT_FOUND) weight = FC_WEIGHT_MEDIUM; +#ifdef FC_WEIGHT_ULTRALIGHT + else if (fontDesc.Find(wxS("Ultra-Light")) != wxNOT_FOUND) weight = FC_WEIGHT_ULTRALIGHT; +#endif + else if (fontDesc.Find(wxS("Light")) != wxNOT_FOUND) weight = FC_WEIGHT_LIGHT; + else if (fontDesc.Find(wxS("Semi-Bold")) != wxNOT_FOUND) weight = FC_WEIGHT_DEMIBOLD; +#ifdef FC_WEIGHT_ULTRABOLD + else if (fontDesc.Find(wxS("Ultra-Bold")) != wxNOT_FOUND) weight = FC_WEIGHT_ULTRABOLD; +#endif + else if (fontDesc.Find(wxS("Bold")) != wxNOT_FOUND) weight = FC_WEIGHT_BOLD; + else if (fontDesc.Find(wxS("Heavy")) != wxNOT_FOUND) weight = FC_WEIGHT_BLACK; + + // Check font width + int width = FC_WIDTH_NORMAL; + if (fontDesc.Find(wxS("Ultra-Condensed")) != wxNOT_FOUND) width = FC_WIDTH_ULTRACONDENSED; + else if (fontDesc.Find(wxS("Extra-Condensed")) != wxNOT_FOUND) width = FC_WIDTH_EXTRACONDENSED; + else if (fontDesc.Find(wxS("Semi-Condensed")) != wxNOT_FOUND) width = FC_WIDTH_SEMICONDENSED; + else if (fontDesc.Find(wxS("Condensed")) != wxNOT_FOUND) width = FC_WIDTH_CONDENSED; + else if (fontDesc.Find(wxS("Ultra-Expanded")) != wxNOT_FOUND) width = FC_WIDTH_ULTRAEXPANDED; + else if (fontDesc.Find(wxS("Extra-Expanded")) != wxNOT_FOUND) width = FC_WIDTH_EXTRAEXPANDED; + else if (fontDesc.Find(wxS("Semi-Expanded")) != wxNOT_FOUND) width = FC_WIDTH_SEMIEXPANDED; + else if (fontDesc.Find(wxS("Expanded")) != wxNOT_FOUND) width = FC_WIDTH_EXPANDED; + + FcResult res; + FcPattern* matchPattern = FcPatternBuild(NULL, FC_FAMILY, FcTypeString, (FcChar8*) fontFamily, NULL); + ScopeGuard sg_mp([matchPattern]() { FcPatternDestroy(matchPattern); }); + + FcPatternAddInteger(matchPattern, FC_SLANT, slant); + FcPatternAddInteger(matchPattern, FC_WEIGHT, weight); + FcPatternAddInteger(matchPattern, FC_WIDTH, width); + + FcConfigSubstitute (NULL, matchPattern, FcMatchPattern); + FcDefaultSubstitute (matchPattern); + + FcPattern* resultPattern = FcFontMatch (NULL, matchPattern, &res); + if (resultPattern == nullptr) return ""; + ScopeGuard sg_rp([resultPattern]() { FcPatternDestroy(resultPattern); }); + + + FcChar8 *fileName; + if (FcPatternGetString(resultPattern, FC_FILE, 0, &fileName) != FcResultMatch) return ""; + wxString fontFileName = wxString::FromUTF8((char *) fileName); + + if (fontFileName.IsEmpty()) return ""; + + // find full file path + wxFileName myFileName(fontFileName); + if (!myFileName.IsOk()) return ""; + + if (myFileName.IsRelative()) { + // Check whether the file is relative to the current working directory + if (!(myFileName.MakeAbsolute() && myFileName.FileExists())) { + return ""; + // File not found, search in given search paths + //wxString foundFileName = m_searchPaths.FindAbsoluteValidPath(fileName); + //if (!foundFileName.IsEmpty()) { + // myFileName.Assign(foundFileName); + //} + } + } + + if (!myFileName.FileExists() || !myFileName.IsFileReadable()) return ""; + + // File exists and is accessible + wxString fullFileName = myFileName.GetFullPath(); + return fullFileName.c_str(); + } +}; +#endif // __linux__ + } // namespace Slic3r using namespace Slic3r; @@ -419,7 +519,7 @@ void GLGizmoEmboss::draw_window() void GLGizmoEmboss::draw_font_list() { const float& max_width = m_gui_cfg->max_font_name_width; - std::optional rename_index; + std::optional rename_index; std::string current_name = imgui_trunc(m_font_list[m_font_selected].name, max_width); ImGui::SetNextItemWidth(m_gui_cfg->combo_font_width); if (ImGui::BeginCombo("##font_selector", current_name.c_str())) { @@ -443,12 +543,12 @@ void GLGizmoEmboss::draw_font_list() for (FontItem &f : m_font_list) { ImGui::PushID(f.name.c_str()); std::string name = imgui_trunc(f.name, max_width); - int index = &f - &m_font_list.front(); - bool is_selected = index == static_cast(m_font_selected); + size_t index = &f - &m_font_list.front(); + bool is_selected = index == m_font_selected; auto flags = ImGuiSelectableFlags_AllowItemOverlap; // allow clic buttons if (ImGui::Selectable(name.c_str(), is_selected, flags)) { size_t prev_font_selected = m_font_selected; - m_font_selected = index; + m_font_selected = index; if (!load_font()) { m_font_selected = prev_font_selected; } else { @@ -475,7 +575,7 @@ void GLGizmoEmboss::draw_font_list() // rename modal window popup const char *rename_popup_id = "Rename_font"; - static int rename_id; + static size_t rename_id; if (rename_index.has_value() && !ImGui::IsPopupOpen(rename_popup_id)) { ImGui::OpenPopup(rename_popup_id); rename_id = *rename_index; @@ -967,8 +1067,10 @@ std::optional WxFontUtils::load_font(const FontItem &fi) return Emboss::load_font(fi.path.c_str()); case FontItem::Type::wx_font_descr: return WxFontUtils::load_font(WxFontUtils::load_wxFont(fi.path)); + case FontItem::Type::undefined: + default: + return {}; } - return {}; } std::optional WxFontUtils::load_font(const wxFont &font) @@ -977,6 +1079,11 @@ std::optional WxFontUtils::load_font(const wxFont &font) #ifdef _WIN32 return Emboss::load_font(font.GetHFONT()); #elif __linux__ // if defined(__WXGTK__) + static FontConfigHelp help; + std::string font_path = help.get_font_path(font); + if (font_path.empty()) return {}; + return Emboss::load_font(font_path.c_str()); + // HERE is place to add implementation for linux to // convert from wxFont to filePath(as MacOS) or fontData pointer(as WinOs) return {};