diff --git a/src/libslic3r/Emboss.cpp b/src/libslic3r/Emboss.cpp index e27ad54717..02c7506983 100644 --- a/src/libslic3r/Emboss.cpp +++ b/src/libslic3r/Emboss.cpp @@ -25,13 +25,7 @@ public: Privat() = delete; static std::optional load_font_info(const Emboss::Font &font); - - struct Glyph - { - Polygons polygons; - int advance_width, left_side_bearing; - }; - static std::optional get_glyph(stbtt_fontinfo &font_info, int unicode_letter, float flatness = 2.f); + static std::optional get_glyph(stbtt_fontinfo &font_info, int unicode_letter, float flatness = 2.f); }; std::optional Privat::load_font_info(const Emboss::Font &font) @@ -49,7 +43,7 @@ std::optional Privat::load_font_info(const Emboss::Font &font) return font_info; } -std::optional Privat::get_glyph(stbtt_fontinfo &font_info, int unicode_letter, float flatness) +std::optional Privat::get_glyph(stbtt_fontinfo &font_info, int unicode_letter, float flatness) { int glyph_index = stbtt_FindGlyphIndex(&font_info, unicode_letter); if (glyph_index == 0) { @@ -58,7 +52,7 @@ std::optional Privat::get_glyph(stbtt_fontinfo &font_info, int un return {}; } - Privat::Glyph glyph; + Emboss::Glyph glyph; stbtt_GetGlyphHMetrics(&font_info, glyph_index, &glyph.advance_width, &glyph.left_side_bearing); stbtt_vertex *vertices; @@ -96,16 +90,15 @@ std::optional Privat::get_glyph(stbtt_fontinfo &font_info, int un // change outer cw to ccw and inner ccw to cw order std::reverse(pts.begin(), pts.end()); - glyph.polygons.emplace_back(pts); } - + // fix for bad defined fonts + glyph.polygons = union_(glyph.polygons); // inner cw - hole // outer ccw - contour return glyph; } - #ifdef _WIN32 #include #include @@ -210,23 +203,46 @@ void choose_font_dlg() { void get_OS_font() { - HGDIOBJ g_hfFont = GetStockObject(DEFAULT_GUI_FONT); LOGFONT lf; + HGDIOBJ g_hfFont = GetStockObject(DEFAULT_GUI_FONT); GetObject(g_hfFont, sizeof(LOGFONT), &lf); - std::wcout << "Default WIN font is " << (std::wstring) lf.lfFaceName - << std::endl; + std::wcout << "DEFAULT_GUI_FONT is " << (std::wstring) lf.lfFaceName << std::endl; + + g_hfFont = GetStockObject(OEM_FIXED_FONT); + GetObject(g_hfFont, sizeof(LOGFONT), &lf); + std::wcout << "OEM_FIXED_FONT is " << (std::wstring) lf.lfFaceName << std::endl; + + g_hfFont = GetStockObject(ANSI_FIXED_FONT); + GetObject(g_hfFont, sizeof(LOGFONT), &lf); + std::wcout << "ANSI_FIXED_FONT is " << (std::wstring) lf.lfFaceName << std::endl; + + g_hfFont = GetStockObject(ANSI_VAR_FONT); + GetObject(g_hfFont, sizeof(LOGFONT), &lf); + std::wcout << "ANSI_VAR_FONT is " << (std::wstring) lf.lfFaceName << std::endl; + + g_hfFont = GetStockObject(SYSTEM_FONT); + GetObject(g_hfFont, sizeof(LOGFONT), &lf); + std::wcout << "SYSTEM_FONT is " << (std::wstring) lf.lfFaceName << std::endl; + + g_hfFont = GetStockObject(DEVICE_DEFAULT_FONT); + GetObject(g_hfFont, sizeof(LOGFONT), &lf); + std::wcout << "DEVICE_DEFAULT_FONT is " << (std::wstring) lf.lfFaceName << std::endl; + + g_hfFont = GetStockObject(SYSTEM_FIXED_FONT); + GetObject(g_hfFont, sizeof(LOGFONT), &lf); + std::wcout << "SYSTEM_FIXED_FONT is " << (std::wstring) lf.lfFaceName << std::endl; } -//#include Emboss::FontList Emboss::get_font_list() { //auto a = get_font_path(L"none"); - //get_OS_font(); + get_OS_font(); //choose_font_dlg(); //FontList list1 = get_font_list_by_enumeration(); //FontList list2 = get_font_list_by_register(); - //FontList list3 = get_font_list_by_folder(); + //FontList list3 = get_font_list_by_folder(); + return get_font_list_by_register(); } @@ -337,9 +353,11 @@ Emboss::FontList Emboss::get_font_list_by_folder() { std::wstring search_dir = std::wstring(winDir, winDir_size) + L"\\Fonts\\"; WIN32_FIND_DATA fd; HANDLE hFind; - auto iterate_files = [&hFind, &fd, &search_dir, &result]() { - if (hFind == INVALID_HANDLE_VALUE) return; - // read all (real) files in current folder + // By https://en.wikipedia.org/wiki/TrueType has also suffix .tte + std::vector suffixes = {L"*.ttf", L"*.ttc", L"*.tte"}; + for (const std::wstring &suffix : suffixes) { + hFind = ::FindFirstFile((search_dir + suffix).c_str(), &fd); + if (hFind == INVALID_HANDLE_VALUE) continue; do { // skip folder . and .. if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue; @@ -347,13 +365,8 @@ Emboss::FontList Emboss::get_font_list_by_folder() { // TODO: find font name instead of filename result.emplace_back(file_name, search_dir + file_name); } while (::FindNextFile(hFind, &fd)); - ::FindClose(hFind); - }; - - hFind = ::FindFirstFile((search_dir + L"*.ttf").c_str(), &fd); - iterate_files(); - hFind = ::FindFirstFile((search_dir + L"*.ttc").c_str(), &fd); - iterate_files(); + ::FindClose(hFind); + } return result; } @@ -366,6 +379,34 @@ std::optional Emboss::get_font_path(const std::wstring &font_face_ } #endif +std::optional Emboss::load_font(std::vector data) +{ + Font res; + res.buffer = std::move(data); + + unsigned int index = 0; + int font_offset = 0; + while (font_offset >= 0) { + font_offset = stbtt_GetFontOffsetForIndex(res.buffer.data(), index++); + } + // at least one font must be inside collection + if (index < 1) { + std::cerr << "There is no font collection inside file."; + return {}; + } + // select default font on index 0 + res.index = 0; + res.count = index; + + auto font_info = Privat::load_font_info(res); + if (!font_info.has_value()) return {}; + + // load information about line gap + stbtt_GetFontVMetrics(&(*font_info), &res.ascent, &res.descent, + &res.linegap); + return res; +} + std::optional Emboss::load_font(const char *file_path) { FILE *file = fopen(file_path, "rb"); @@ -386,52 +427,63 @@ std::optional Emboss::load_font(const char *file_path) } rewind(file); - Font res; - res.buffer = std::vector(size); - size_t count_loaded_bytes = fread((void *) &res.buffer.front(), 1, size, file); - - unsigned int index = 0; - int font_offset = 0; - while (font_offset >= 0) { - font_offset = stbtt_GetFontOffsetForIndex(res.buffer.data(), index++); + std::vector buffer(size); + size_t count_loaded_bytes = fread((void *) &buffer.front(), 1, size, file); + if (count_loaded_bytes != size) { + std::cerr << "Different loaded(from file) data size."; + return {}; } - // at least one font must be inside collection - if (index < 1) { - std::cerr << "There is no font collection inside file."; - return {}; - } - // select default font on index 0 - res.index = 0; - res.count = index; - - auto font_info = Privat::load_font_info(res); - if (!font_info.has_value()) return {}; - - // load information about line gap - stbtt_GetFontVMetrics(&(*font_info), &res.ascent, &res.descent, &res.linegap); - return res; + return load_font(std::move(buffer)); } -Polygons Emboss::letter2polygons(const Font &font, char letter, float flatness) + +#ifdef _WIN32 +std::optional Emboss::load_font(HFONT hfont) +{ + HDC hdc = ::CreateCompatibleDC(NULL); + if (hdc == NULL) { + std::cerr << "Can't create HDC by CreateCompatibleDC(NULL)."; + return {}; + } + + ::SelectObject(hdc, hfont); + size_t size = ::GetFontData(hdc, 0, 0, NULL, 0); + if (size == 0) { + std::cerr << "HFONT doesn't have size."; + ::DeleteDC(hdc); + return {}; + } + + std::vector buffer(size); + size_t loaded_size = ::GetFontData(hdc, 0, 0, buffer.data(), size); + ::DeleteDC(hdc); + + if (size != loaded_size) { + std::cerr << "Different loaded(from HFONT) data size."; + return {}; + } + + return load_font(std::move(buffer)); +} +#endif // _WIN32 + +std::optional Emboss::letter2glyph(const Font &font, + int letter, + float flatness) { auto font_info_opt = Privat::load_font_info(font); - if (!font_info_opt.has_value()) return Polygons(); + if (!font_info_opt.has_value()) return {}; stbtt_fontinfo *font_info = &(*font_info_opt); - - auto glyph_opt = Privat::get_glyph(*font_info_opt, (int) letter, flatness); - if (!glyph_opt.has_value()) return Polygons(); - - return union_(glyph_opt->polygons); + return Privat::get_glyph(*font_info_opt, (int) letter, flatness); } Polygons Emboss::text2polygons(const Font & font, const char * text, - const FontProp &font_prop) + const FontProp &font_prop, + Glyphs & cache) { - auto font_info_opt = Privat::load_font_info(font); - if (!font_info_opt.has_value()) return Polygons(); - stbtt_fontinfo *font_info = &(*font_info_opt); - + std::optional font_info_opt; + Point cursor(0, 0); Polygons result; @@ -443,16 +495,27 @@ Polygons Emboss::text2polygons(const Font & font, continue; } int unicode = static_cast(wc); - auto glyph_opt = Privat::get_glyph(*font_info_opt, unicode, font_prop.flatness); - if (!glyph_opt.has_value()) continue; - + std::optional glyph_opt; + auto glyph_item = cache.find(unicode); + if (glyph_item != cache.end()) glyph_opt = glyph_item->second; + else { + if (!font_info_opt.has_value()) { + font_info_opt = Privat::load_font_info(font); + // can load font info? + if (!font_info_opt.has_value()) return Polygons(); + } + glyph_opt = Privat::get_glyph(*font_info_opt, unicode, + font_prop.flatness); + // has definition inside of font? + if (!glyph_opt.has_value()) continue; + cache[unicode] = *glyph_opt; + } + // move glyph to cursor position Polygons polygons = glyph_opt->polygons; // copy for (Polygon &polygon : polygons) - for (Point &p : polygon.points) p += cursor; - + polygon.translate(cursor); cursor.x() += glyph_opt->advance_width + font_prop.char_gap; - polygons_append(result, polygons); } return union_(result); diff --git a/src/libslic3r/Emboss.hpp b/src/libslic3r/Emboss.hpp index c334a34dac..1a38b537a7 100644 --- a/src/libslic3r/Emboss.hpp +++ b/src/libslic3r/Emboss.hpp @@ -75,30 +75,49 @@ public: FontProp() = default; }; + // description of one letter + struct Glyph + { + Polygons polygons; + int advance_width, left_side_bearing; + }; + // cache for glyph by unicode + using Glyphs = std::map; + /// /// Load font file into buffer /// /// Location of .ttf or .ttc font file /// Font object when loaded. static std::optional load_font(const char *file_path); + static std::optional load_font(std::vector data); +#ifdef _WIN32 + // fix for unknown pointer HFONT + using HFONT = void*; + static std::optional load_font(HFONT hfont); +#endif // _WIN32 /// /// convert letter into polygons /// /// Define fonts - /// One character to convert + /// One character defined by unicode codepoint /// Precision of lettter outline curve in conversion to lines /// inner polygon cw(outer ccw) - static Polygons letter2polygons(const Font &font, char letter, float flatness); + static std::optional letter2glyph(const Font &font, int letter, float flatness); /// /// Convert text into polygons /// /// Define fonts /// Characters to convert - /// User defined property of font + /// User defined property of the font + /// Cache for letter polygons /// Inner polygon cw(outer ccw) - static Polygons text2polygons(const Font &font, const char *text, const FontProp& font_prop); + static Polygons text2polygons(const Font & font, + const char * text, + const FontProp &font_prop, + Glyphs & cache = Glyphs()); /// /// Project 2d point into space diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index ebc28c8cfb..dc990fc667 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -433,7 +433,7 @@ wxString file_wildcards(FileType file_type, const std::string &custom_extension) /* FT_GCODE */ "G-code files (*.gcode, *.gco, *.g, *.ngc)|*.gcode;*.GCODE;*.gco;*.GCO;*.g;*.G;*.ngc;*.NGC", /* FT_MODEL */ "Known files (*.stl, *.obj, *.amf, *.xml, *.3mf, *.prusa)|*.stl;*.STL;*.obj;*.OBJ;*.amf;*.AMF;*.xml;*.XML;*.3mf;*.3MF;*.prusa;*.PRUSA", /* FT_PROJECT */ "Project files (*.3mf, *.amf)|*.3mf;*.3MF;*.amf;*.AMF", - /* FT_FONTS */ "Font files (*.ttf, *.ttc)|*.ttf;*.TTF;*.ttc;*.TTC", + /* FT_FONTS */ "Font files (*.ttf, *.tte, *.ttc, *.dfont)|*.ttf;*.tte;*.ttc;*.dfont;*.TTF;*.TTE;*.TTC;*.DFONT", /* FT_GALLERY */ "Known files (*.stl, *.obj)|*.stl;*.STL;*.obj;*.OBJ", /* FT_INI */ "INI files (*.ini)|*.ini;*.INI", diff --git a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp index d3d85b3ab3..b0e6d7427c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp @@ -8,6 +8,9 @@ #include "libslic3r/Model.hpp" +#include +#include + namespace Slic3r::GUI { GLGizmoEmboss::GLGizmoEmboss(GLCanvas3D & parent, @@ -21,7 +24,8 @@ GLGizmoEmboss::GLGizmoEmboss(GLCanvas3D & parent, , m_text_size(255) , m_text(new char[m_text_size]) , m_scale(0.01f) - , m_emboss(5.f) + , m_emboss(5.f) + , m_volume(nullptr) { // TODO: suggest to use https://fontawesome.com/ // (copy & paste) unicode symbols from web @@ -63,18 +67,17 @@ void GLGizmoEmboss::on_render_for_picking() {} void GLGizmoEmboss::on_render_input_window(float x, float y, float bottom_limit) { + if (!m_gui_cfg.has_value()) m_gui_cfg.emplace(GuiCfg()); + int flag = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse; m_imgui->begin(on_get_name(), flag); - - size_t max_font_name = 20; // count characters - auto& current = m_font_list[m_font_selected]; if (ImGui::BeginCombo("##font_selector", current.name.c_str())) { for (const Emboss::FontItem &f : m_font_list) { ImGui::PushID((void*)&f.name); - std::string name = (f.name.size() < max_font_name) ? - f.name : (f.name.substr(0,max_font_name - 3) + " .."); + std::string name = (f.name.size() < m_gui_cfg->max_font_name) ? + f.name : (f.name.substr(0,m_gui_cfg->max_font_name - 3) + " .."); if (ImGui::Selectable(name.c_str(), &f == ¤t)) { m_font_selected = &f - &m_font_list.front(); load_font(); @@ -90,28 +93,52 @@ void GLGizmoEmboss::on_render_input_window(float x, float y, float bottom_limit) ImGui::EndCombo(); } ImGui::SameLine(); - m_imgui->disabled_begin(!m_font.has_value() || m_font->count == 1); - if (ImGui::BeginCombo("##font_collection_selector", std::to_string(m_font->index).c_str())) { - for (size_t i = 0; i < m_font->count; ++i) { - ImGui::PushID(1<<10 + i); - if (ImGui::Selectable(std::to_string(i).c_str(), i == m_font->index)) { - m_font->index = i; + if (m_font.has_value()) { + if (ImGui::BeginCombo("##font_collection_selector", std::to_string(m_font->index).c_str())) { + for (size_t i = 0; i < m_font->count; ++i) { + ImGui::PushID(1 << 10 + i); + if (ImGui::Selectable(std::to_string(i).c_str(), + i == m_font->index)) { + m_font->index = i; + } + ImGui::PopID(); } - ImGui::PopID(); + ImGui::EndCombo(); } - ImGui::EndCombo(); } - m_imgui->disabled_end(); + + static std::string fontName; + if (ImGui::Button(_L("choose font").c_str())) { + static wxFontData data; // keep last selected font + wxFontDialog font_dialog(nullptr, data); + font_dialog.SetTitle(_L("Select font FFF")); + if (font_dialog.ShowModal() == wxID_OK) { + data = font_dialog.GetFontData(); + wxFont font = data.GetChosenFont(); + fontName = boost::nowide::narrow(font.GetFaceName()); + m_font = Emboss::load_font(font.GetHFONT()); + m_font_glyph_cache.clear(); + process(); + } + } + if (!fontName.empty()) ImGui::Text(fontName.c_str()); ImGui::SameLine(); draw_add_button(); ImGui::InputFloat("Scale", &m_scale); ImGui::InputFloat("Emboss", &m_emboss); - ImGui::InputFloat("Flatness", &m_font_prop.flatness); + if (ImGui::InputFloat("Flatness", &m_font_prop.flatness)) + m_font_glyph_cache.clear(); ImGui::InputInt("CharGap", &m_font_prop.char_gap); ImGui::InputInt("LineGap", &m_font_prop.line_gap); + ImGui::InputFloat3("Origin", m_orientation.origin.data()); + //if (ImGui::InputFloat3("Normal", m_normal.data())) m_normal.normalize(); + //if (ImGui::InputFloat3("Up", m_up.data())) m_up.normalize(); + + + m_imgui->disabled_begin(!m_font.has_value()); if (ImGui::Button("Preview")) process(); m_imgui->disabled_end(); @@ -129,12 +156,12 @@ void GLGizmoEmboss::on_render_input_window(float x, float y, float bottom_limit) } // change text size - int max_text_size = m_text_size; + int max_text_size = static_cast(m_text_size); if (ImGui::InputInt("max text size", &max_text_size, 8, 64)) { if (max_text_size < 4) max_text_size = 4; std::unique_ptr newData(new char[max_text_size]); size_t index = 0; - while (index < max_text_size-1) { + while ((index+1) < max_text_size) { if (m_text.get()[index] == '\0') break; newData.get()[index] = m_text.get()[index]; ++index; @@ -165,7 +192,7 @@ void GLGizmoEmboss::on_set_state() // Closing gizmo. e.g. selecting another one if (GLGizmoBase::m_state == GLGizmoBase::Off) { - // refuse outgoing during simlification + // refuse outgoing during text preview if (false) { GLGizmoBase::m_state = GLGizmoBase::On; auto notification_manager = wxGetApp().plater()->get_notification_manager(); @@ -175,36 +202,115 @@ void GLGizmoEmboss::on_set_state() _u8L("ERROR: Wait until ends or Cancel process.")); return; } - + m_volume = nullptr; } else if (GLGizmoBase::m_state == GLGizmoBase::On) { // when open by hyperlink it needs to show up //request_rerender(); } } -void GLGizmoEmboss::process() { - auto project = std::make_unique( - std::make_unique(m_emboss/m_scale), m_scale); +// IMPROVE: Do not use gizmo_event - especialy smth with prefix SLA, +// use Bind into wxGLCanvas? +bool GLGizmoEmboss::gizmo_event(SLAGizmoEventType action, + const Vec2d & mouse_position, + bool shift_down, + bool alt_down, + bool control_down) +{ + /* if (action == SLAGizmoEventType::LeftUp) { + const Camera & camera = wxGetApp().plater()->get_camera(); + const Selection & selection = m_parent.get_selection(); + const ModelObject * mo = m_c->selection_info()->model_object(); + const ModelInstance *mi = mo->instances[selection.get_instance_idx()]; + const Transform3d & instance_trafo = mi->get_transformation() + .get_matrix(); - Polygons polygons = Emboss::text2polygons(*m_font, m_text.get(), m_font_prop); + // Precalculate transformations of individual meshes. + std::vector trafo_matrices; + for (const ModelVolume *mv : mo->volumes) + if (mv->is_model_part()) + trafo_matrices.emplace_back(instance_trafo * mv->get_matrix()); + + Vec3f normal = Vec3f::Zero(); + Vec3f hit = Vec3f::Zero(); + size_t facet = 0; + Vec3f closest_hit = Vec3f::Zero(); + double closest_hit_squared_distance = + std::numeric_limits::max(); + size_t closest_facet = 0; + int closest_hit_mesh_id = -1; + + // Cast a ray on all meshes, pick the closest hit and save it for the + // respective mesh + for (int mesh_id = 0; mesh_id < int(trafo_matrices.size()); + ++mesh_id) { + if (m_c->raycaster()->raycasters()[mesh_id]->unproject_on_mesh( + mouse_position, trafo_matrices[mesh_id], camera, hit, + normal, m_c->object_clipper()->get_clipping_plane(), + &facet)) { + + // In case this hit is clipped, skip it. + + // Is this hit the closest to the camera so far? + double hit_squared_distance = (camera.get_position() - + trafo_matrices[mesh_id] * + hit.cast()) + .squaredNorm(); + if (hit_squared_distance < closest_hit_squared_distance) { + closest_hit_squared_distance = hit_squared_distance; + closest_facet = facet; + closest_hit_mesh_id = mesh_id; + closest_hit = hit; + } + } + } + + // get intersection + + } + */ + return false; +} + +void GLGizmoEmboss::process() { + if (!m_font.has_value()) return; + + Polygons polygons = Emboss::text2polygons(*m_font, m_text.get(), m_font_prop, m_font_glyph_cache); if (polygons.empty()) return; + auto project = std::make_unique( + std::make_unique(m_emboss/m_scale), m_scale); indexed_triangle_set its = Emboss::polygons2model(polygons, *project); if (its.indices.empty()) return; // add object - TriangleMesh tm(its); + TriangleMesh tm(std::move(its)); tm.repair(); - tm.WriteOBJFile("text_preview.obj"); + //tm.WriteOBJFile("text_preview.obj"); const Selection &selection = m_parent.get_selection(); int object_idx = selection.get_object_idx(); ModelObject * obj = wxGetApp().plater()->model().objects[object_idx]; - ModelVolume * v = obj->volumes.front(); - v->set_mesh(tm); - v->set_new_unique_id(); - obj->invalidate_bounding_box(); + + //if (m_volume != nullptr) { + // // TODO: fix index of m_volume + // size_t m_volume_index = obj->volumes.size() - 1; + // obj->delete_volume(m_volume_index); + //} + //m_volume = obj->add_volume(std::move(tm), ModelVolumeType::MODEL_PART); + + if (m_volume == nullptr) { + m_volume = obj->add_volume(std::move(tm), ModelVolumeType::MODEL_PART); + } else { + m_volume->set_mesh(std::move(tm)); + m_volume->set_new_unique_id(); + m_volume->translate(-m_volume->source.mesh_offset); + + m_volume->center_geometry_after_creation(true); + m_volume->calculate_convex_hull(); + m_volume->get_object()->invalidate_bounding_box(); + } m_parent.reload_scene(true); } @@ -235,7 +341,7 @@ void GLGizmoEmboss::draw_add_button() { font_list.emplace_back(name, path); } // set last added font as active - m_font_selected = m_font_list.size() - 1; + m_font_selected = m_font_list.size() + font_list.size() - 1; add_fonts(font_list); load_font(); } @@ -250,6 +356,7 @@ bool GLGizmoEmboss::load_font() { auto font_path = m_font_list[m_font_selected].path.c_str(); m_font = Emboss::load_font(font_path); + m_font_glyph_cache.clear(); return m_font.has_value(); } @@ -279,5 +386,4 @@ void GLGizmoEmboss::add_fonts(const Emboss::FontList &font_list) { sort_fonts(); } - } // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp index 7e433da0cc..5c9154539e 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp @@ -4,11 +4,14 @@ // Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, // which overrides our localization "L" macro. #include "GLGizmoBase.hpp" +#include "GLGizmosCommon.hpp" + #include "admesh/stl.h" // indexed_triangle_set #include #include #include "libslic3r/Emboss.hpp" +#include "libslic3r/Point.hpp" namespace Slic3r { class ModelVolume; @@ -19,6 +22,8 @@ class GLGizmoEmboss : public GLGizmoBase public: GLGizmoEmboss(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); virtual ~GLGizmoEmboss(); + // pseudo virtual function, no inheritance + virtual bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down); protected: virtual bool on_init() override; virtual std::string on_get_name() const override; @@ -27,7 +32,7 @@ protected: virtual void on_render_input_window(float x, float y, float bottom_limit) override; virtual bool on_is_activable() const override; virtual bool on_is_selectable() const override { return true; } - virtual void on_set_state() override; + virtual void on_set_state() override; private: void process(); @@ -42,7 +47,8 @@ private: // so the change takes effect. (info by GLGizmoFdmSupports.hpp) struct GuiCfg { - + const size_t max_font_name = 20; // count characters + GuiCfg() = default; }; std::optional m_gui_cfg; @@ -50,14 +56,28 @@ private: size_t m_font_selected;// index to m_font_list std::optional m_font; + Emboss::Glyphs m_font_glyph_cache; size_t m_text_size; std::unique_ptr m_text; Emboss::FontProp m_font_prop; + // text position + struct Orientation + { + Vec3f origin = Vec3f(0.f, 0.f, 0.f); + Vec3f normal = Vec3f(0.f, 0.f, 1.f); + Vec3f up = Vec3f(0.f, 1.f, 0.f); + Orientation() = default; + }; + Orientation m_orientation; + float m_scale; float m_emboss; + + // actual volume + ModelVolume *m_volume; }; } // namespace GUI diff --git a/tests/libslic3r/test_meshboolean.cpp b/tests/libslic3r/test_meshboolean.cpp index 7d60054ad7..11e4004fde 100644 --- a/tests/libslic3r/test_meshboolean.cpp +++ b/tests/libslic3r/test_meshboolean.cpp @@ -54,7 +54,7 @@ TEST_CASE("Add TriangleMeshes", "[MeshBoolean]") Polygons ttf2polygons(const char * font_name, char letter, float flatness = 1.f) { auto font = Emboss::load_font(font_name); if (!font.has_value()) return Polygons(); - return Emboss::letter2polygons(*font, letter, flatness); + return Emboss::letter2glyph(*font, letter, flatness)->polygons; } #include "libslic3r/SVG.hpp"