Second try on linux platform with fontconfig

This commit is contained in:
Filip Sykala 2021-10-13 11:12:17 +02:00
parent 69aae0fab7
commit 68c4a396ac

View File

@ -33,6 +33,10 @@
#define USE_FONT_DIALOG
#endif // apple
#ifdef __linux__
#include <fontconfig/fontconfig.h>
#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<int> rename_index;
std::optional<size_t> 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<int>(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<Emboss::Font> 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<Emboss::Font> WxFontUtils::load_font(const wxFont &font)
@ -977,6 +1079,11 @@ std::optional<Emboss::Font> 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 {};