diff --git a/src/libslic3r/Emboss.cpp b/src/libslic3r/Emboss.cpp index 69d3cf460d..974f076787 100644 --- a/src/libslic3r/Emboss.cpp +++ b/src/libslic3r/Emboss.cpp @@ -521,6 +521,42 @@ std::unique_ptr Emboss::load_font(const char *file_path) #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; +} + +void * Emboss::can_load(HFONT hfont) +{ + DWORD dwTable=0, dwOffset=0; + size_t size = 0; + if (!load_hfont(hfont, dwTable, dwOffset, size)) return nullptr; + return hfont; +} + std::unique_ptr Emboss::load_font(HFONT hfont) { HDC hdc = ::CreateCompatibleDC(NULL); @@ -529,23 +565,11 @@ std::unique_ptr Emboss::load_font(HFONT hfont) return nullptr; } - // To retrieve the data from the beginning of the file for TrueType - // Collection files specify 'ttcf' (0x66637474). - DWORD dwTable = 0x66637474; - DWORD dwOffset = 0; - - ::SelectObject(hdc, hfont); - size_t 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) { - std::cerr << "HFONT doesn't have size." << std::endl; + DWORD dwTable=0,dwOffset = 0; + size_t size; + if (!load_hfont(hfont, dwTable, dwOffset, size, hdc)) { ::DeleteDC(hdc); - return nullptr; + return nullptr; } std::vector buffer(size); diff --git a/src/libslic3r/Emboss.hpp b/src/libslic3r/Emboss.hpp index f4d30ba7a4..d15db8ddf6 100644 --- a/src/libslic3r/Emboss.hpp +++ b/src/libslic3r/Emboss.hpp @@ -95,6 +95,7 @@ public: #ifdef _WIN32 // fix for unknown pointer HFONT using HFONT = void*; + static void * can_load(HFONT hfont); static std::unique_ptr load_font(HFONT hfont); #endif // _WIN32 diff --git a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp index dee5625654..4617e56294 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp @@ -688,20 +688,55 @@ void GLGizmoEmboss::draw_text_input() if (exist_change) m_font_manager.get_imgui_font(m_text); } +#include "wx/fontenum.h" void GLGizmoEmboss::draw_font_list() { - if (ImGui::BeginCombo("##font_selector", "Actual selected font")) { - std::vector fonts = {1, 3, 5, 8}; - for (const auto &item : fonts) { - size_t index = &item - &fonts.front(); + class MyFontEnumerator : public wxFontEnumerator + { + wxArrayString m_facenames; + wxFontEncoding m_encoding; + bool m_is_init; + public: + MyFontEnumerator(wxFontEncoding encoding) : m_encoding(encoding), m_is_init(false){} + const wxArrayString& get_facenames() const{ return m_facenames; } + bool is_init() const { return m_is_init; } + bool init() { + if (m_is_init) return false; + m_is_init = true; + bool fixedWidthOnly = false; + if (!wxFontEnumerator::EnumerateFacenames(m_encoding, fixedWidthOnly)) return false; + if (m_facenames.empty()) return false; + return true; + } + protected: + virtual bool OnFacename(const wxString& facename) wxOVERRIDE { + // vertical font start with @, we will filter it out + if (facename.empty() || facename[0] == '@') return true; + wxFont wx_font(wxFontInfo().FaceName(facename).Encoding(m_encoding)); + void *addr = WxFontUtils::can_load(wx_font); + if (addr == nullptr) return true; // can't load + m_facenames.Add(facename); + return true; + } + }; + wxFontEncoding encoding = wxFontEncoding::wxFONTENCODING_SYSTEM; + static MyFontEnumerator fontEnumerator(encoding); + std::optional &wx_font_opt = m_font_manager.get_wx_font(); + wxString actual_face_name = wx_font_opt.has_value() ? + wx_font_opt->GetFaceName() : ""; + const char * selected = (!actual_face_name.empty()) ? + actual_face_name.ToUTF8().data() : " --- "; + if (ImGui::BeginCombo("##font_selector", selected)) { + if(!fontEnumerator.is_init()) fontEnumerator.init(); + const wxArrayString &face_names = fontEnumerator.get_facenames(); + ImGui::TextColored(ImGuiWrapper::COL_GREY_LIGHT, "count %d", static_cast(face_names.size())); + for (const wxString &face_name : face_names) { + size_t index = &face_name - &face_names.front(); ImGui::PushID(index); - - bool is_selected = false; - ImGuiSelectableFlags_ flags = - ImGuiSelectableFlags_AllowItemOverlap; // allow click buttons - if (ImGui::Selectable(("font name" + std::to_string(item)).c_str(), - is_selected)) { + bool is_selected = (actual_face_name == face_name); + if (ImGui::Selectable(face_name.ToUTF8().data(), is_selected)) { // Select font + wx_font_opt = wxFont(wxFontInfo().FaceName(face_name).Encoding(encoding)); } ImGui::PopID(); } @@ -1035,6 +1070,7 @@ void GLGizmoEmboss::draw_style_edit() { // store font size into path if (fi.type == WxFontUtils::get_actual_type()) { if (wx_font.has_value()) { + // TODO: check difference wx_font->Scale(float x) wx_font->SetPointSize(font_prop.size_in_mm); fi.path = WxFontUtils::store_wxFont(*wx_font); } diff --git a/src/slic3r/Utils/FontListSerializable.cpp b/src/slic3r/Utils/FontListSerializable.cpp index cf6c4fcbf3..88d0890c3f 100644 --- a/src/slic3r/Utils/FontListSerializable.cpp +++ b/src/slic3r/Utils/FontListSerializable.cpp @@ -17,10 +17,15 @@ const std::string FontListSerializable::APP_CONFIG_FONT_LINE_GAP = "line_gap" FontList FontListSerializable::create_default_font_list() { + // https://docs.wxwidgets.org/3.0/classwx_font.html + // Predefined objects/pointers: wxNullFont, wxNORMAL_FONT, wxSMALL_FONT, wxITALIC_FONT, wxSWISS_FONT return { - WxFontUtils::get_font_item(wxFont(5, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL)) - , WxFontUtils::get_font_item(wxFont(10, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD)) - , WxFontUtils::get_os_font() + WxFontUtils::get_font_item(*wxNORMAL_FONT), // wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) + WxFontUtils::get_font_item(*wxSMALL_FONT), // A font using the wxFONTFAMILY_SWISS family and 2 points smaller than wxNORMAL_FONT. + WxFontUtils::get_font_item(*wxITALIC_FONT), // A font using the wxFONTFAMILY_ROMAN family and wxFONTSTYLE_ITALIC style and of the same size of wxNORMAL_FONT. + WxFontUtils::get_font_item(*wxSWISS_FONT), // A font identic to wxNORMAL_FONT except for the family used which is wxFONTFAMILY_SWISS. + WxFontUtils::get_font_item(wxFont(10, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD)) + //, WxFontUtils::get_os_font() == wxNORMAL_FONT }; } diff --git a/src/slic3r/Utils/FontManager.cpp b/src/slic3r/Utils/FontManager.cpp index 74ea8f6d0d..7252a8f63d 100644 --- a/src/slic3r/Utils/FontManager.cpp +++ b/src/slic3r/Utils/FontManager.cpp @@ -321,7 +321,7 @@ void FontManager::free_imgui_fonts() bool FontManager::load_font(const wxFont &font) { - auto font_ptr = WxFontUtils::load_font(font); + std::unique_ptr font_ptr = WxFontUtils::load_font(font); if (font_ptr == nullptr) return false; m_font_list[m_font_selected].font_file = std::move(font_ptr); load_imgui_font(); @@ -334,6 +334,8 @@ void FontManager::load_imgui_font(const std::string &text) { void FontManager::load_imgui_font(size_t index, const std::string &text) { + free_imgui_fonts(); // TODO: remove it after correct initialization + if (index >= m_font_list.size()) return; Item &item = m_font_list[index]; if (item.font_file == nullptr) return; diff --git a/src/slic3r/Utils/FontManager.hpp b/src/slic3r/Utils/FontManager.hpp index 5aae8df9b7..82b125218b 100644 --- a/src/slic3r/Utils/FontManager.hpp +++ b/src/slic3r/Utils/FontManager.hpp @@ -1,6 +1,7 @@ #ifndef slic3r_FontManager_hpp_ #define slic3r_FontManager_hpp_ +#include #include #include "libslic3r/Emboss.hpp" diff --git a/src/slic3r/Utils/WxFontUtils.cpp b/src/slic3r/Utils/WxFontUtils.cpp index 665515d48e..c34a9e6aed 100644 --- a/src/slic3r/Utils/WxFontUtils.cpp +++ b/src/slic3r/Utils/WxFontUtils.cpp @@ -12,9 +12,26 @@ using namespace Slic3r; using namespace Slic3r::GUI; -std::unique_ptr WxFontUtils::load_font(const wxFont &font) +void *WxFontUtils::can_load(const wxFont &font) { if (!font.IsOk()) return nullptr; +#ifdef _WIN32 + return Emboss::can_load(font.GetHFONT()); +#elif defined(__APPLE__) + // use file path + return font.GetNativeFontInfo(); +#elif defined(__linux__) + // TODO: find better way + static FontConfigHelp help; + std::string font_path = help.get_font_path(font); + if (font_path.empty()) return nullptr; + return Emboss::load_font(font_path.c_str()); +#endif + return nullptr; +} + +std::unique_ptr WxFontUtils::load_font(const wxFont &font) +{ #ifdef _WIN32 return Emboss::load_font(font.GetHFONT()); #elif defined(__APPLE__) diff --git a/src/slic3r/Utils/WxFontUtils.hpp b/src/slic3r/Utils/WxFontUtils.hpp index 0ee1c2ca25..1f5cc56486 100644 --- a/src/slic3r/Utils/WxFontUtils.hpp +++ b/src/slic3r/Utils/WxFontUtils.hpp @@ -15,6 +15,10 @@ public: // only static functions WxFontUtils() = delete; + // check if exist file for wxFont + // return pointer on data or nullptr when can't load + static void *can_load(const wxFont &font); + // os specific load of wxFont static std::unique_ptr load_font(const wxFont &font);