diff --git a/src/slic3r/GUI/Gizmos/GLGizmoText.cpp b/src/slic3r/GUI/Gizmos/GLGizmoText.cpp index 7fcc88433..ddef73880 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoText.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoText.cpp @@ -25,6 +25,7 @@ #include #include "libslic3r/SVG.hpp" #include +#include "wx/fontenum.h" namespace Slic3r { namespace GUI { @@ -35,6 +36,119 @@ static const wxColour FONT_TEXTURE_FG = *wxWHITE; static const int FONT_SIZE = 12; static const float SELECTABLE_INNER_OFFSET = 8.0f; +static std::vector font_black_list = { +#ifdef _WIN32 + "MT Extra", + "Marlett", + "Symbol", + "Webdings", + "Wingdings", + "Wingdings 2", + "Wingdings 3", +#endif +}; + +static const wxFontEncoding font_encoding = wxFontEncoding::wxFONTENCODING_SYSTEM; + +#ifdef _WIN32 +static bool load_hfont(void *hfont, DWORD &dwTable, DWORD &dwOffset, size_t &size, HDC hdc = nullptr) +{ + bool del_hdc = false; + if (hdc == nullptr) { + del_hdc = true; + hdc = ::CreateCompatibleDC(NULL); + if (hdc == NULL) return false; + } + + // To retrieve the data from the beginning of the file for TrueType + // Collection files specify 'ttcf' (0x66637474). + dwTable = 0x66637474; + dwOffset = 0; + + ::SelectObject(hdc, hfont); + size = ::GetFontData(hdc, dwTable, dwOffset, NULL, 0); + if (size == GDI_ERROR) { + // HFONT is NOT TTC(collection) + dwTable = 0; + size = ::GetFontData(hdc, dwTable, dwOffset, NULL, 0); + } + + if (size == 0 || size == GDI_ERROR) { + if (del_hdc) ::DeleteDC(hdc); + return false; + } + return true; +} +#endif // _WIN32 + +bool can_load(const wxFont &font) +{ +#ifdef _WIN32 + DWORD dwTable = 0, dwOffset = 0; + size_t size = 0; + void* hfont = font.GetHFONT(); + if (!load_hfont(hfont, dwTable, dwOffset, size)) + return false; + return hfont != nullptr; +#elif defined(__APPLE__) + return true; +#elif defined(__linux__) + return true; +#endif + return false; +} + +std::vector init_face_names() +{ + std::vector valid_font_names; + wxArrayString facenames = wxFontEnumerator::GetFacenames(font_encoding); + std::vector bad_fonts; + + // validation lambda + auto is_valid_font = [coding = font_encoding, bad = bad_fonts](const wxString &name) { + if (name.empty()) + return false; + + // vertical font start with @, we will filter it out + // Not sure if it is only in Windows so filtering is on all platforms + if (name[0] == '@') + return false; + + // previously detected bad font + auto it = std::lower_bound(bad.begin(), bad.end(), name); + if (it != bad.end() && *it == name) + return false; + + wxFont wx_font(wxFontInfo().FaceName(name).Encoding(coding)); + // Faster chech if wx_font is loadable but not 100% + // names could contain not loadable font + if (!wx_font.IsOk()) + return false; + + if (!can_load(wx_font)) + return false; + + return true; + }; + + std::sort(facenames.begin(), facenames.end()); + for (const wxString &name : facenames) { + if (is_valid_font(name)) { + valid_font_names.push_back(name.ToStdString()); + } + else { + bad_fonts.emplace_back(name); + } + } + assert(std::is_sorted(bad_fonts.begin(), bad_fonts.end())); + + for (auto iter = font_black_list.begin(); iter != font_black_list.end(); ++iter) { + valid_font_names.erase(std::remove(valid_font_names.begin(), valid_font_names.end(), *iter), valid_font_names.end()); + } + + return valid_font_names; +} + class Line_3D { public: @@ -143,7 +257,9 @@ GLGizmoText::~GLGizmoText() bool GLGizmoText::on_init() { - m_avail_font_names = init_occt_fonts(); + m_avail_font_names = init_face_names(); + + //m_avail_font_names = init_occt_fonts(); update_font_texture(); m_scale = m_imgui->get_font_size(); m_shortcut_key = WXK_CONTROL_T;