From 2b31fa7d4aa9bc3796d5810f0017d0e18983adcb Mon Sep 17 00:00:00 2001 From: Filip Sykala - NTB T15p Date: Tue, 10 Jan 2023 08:36:33 +0100 Subject: [PATCH] More info for user in preview of font in combo box. + Clear rest of texture when short text is used --- src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp | 48 +++++++++++++------ src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp | 1 + .../GUI/Jobs/CreateFontNameImageJob.cpp | 44 ++++++++++++----- .../GUI/Jobs/CreateFontNameImageJob.hpp | 6 +++ 4 files changed, 73 insertions(+), 26 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp index dc0b9fed7..952a903bb 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp @@ -1768,33 +1768,46 @@ void GLGizmoEmboss::init_font_name_texture() { void GLGizmoEmboss::draw_font_preview(FaceName& face, bool is_visible) { + // Limit for opened font files at one moment unsigned int &count_opened_fonts = m_face_names.count_opened_font_files; + // Size of texture ImVec2 size(m_gui_cfg->face_name_size.x(), m_gui_cfg->face_name_size.y()); - // set to pixel 0,0 in texture - ImVec2 uv0(0.f, 0.f), uv1(1.f / size.x, 1.f / size.y / m_face_names.count_cached_textures); - ImTextureID tex_id = (void *) (intptr_t) m_face_names.texture_id; + float count_cached_textures_f = static_cast(m_face_names.count_cached_textures); + std::string state_text; + // uv0 and uv1 set to pixel 0,0 in texture + ImVec2 uv0(0.f, 0.f), uv1(1.f / size.x, 1.f / size.y / count_cached_textures_f); if (face.is_created != nullptr) { + // not created preview if (*face.is_created) { + // Already created preview size_t texture_index = face.texture_index; - uv0 = ImVec2(0.f, texture_index / (float) m_face_names.count_cached_textures), - uv1 = ImVec2(1.f, (texture_index + 1) / (float) m_face_names.count_cached_textures); - } else if (!is_visible) { - face.is_created = nullptr; - face.cancel->store(true); + uv0 = ImVec2(0.f, texture_index / count_cached_textures_f); + uv1 = ImVec2(1.f, (texture_index + 1) / count_cached_textures_f); + } else { + // Not finished preview + if (is_visible) { + // when not canceled still loading + state_text = (face.cancel->load())? + _u8L(" No symbol"): + _u8L(" ... Loading"); + } else { + // not finished and not visible cancel job + face.is_created = nullptr; + face.cancel->store(true); + } } } else if (is_visible && count_opened_fonts < m_gui_cfg->max_count_opened_font_files) { ++count_opened_fonts; face.cancel = std::make_shared(false); face.is_created = std::make_shared(false); - std::string text = m_text.empty() ? "AaBbCc" : m_text; - const unsigned char gray_level = 5; // format type and level must match to texture data const GLenum format = GL_RGBA, type = GL_UNSIGNED_BYTE; const GLint level = 0; // select next texture index size_t texture_index = (m_face_names.texture_index + 1) % m_face_names.count_cached_textures; + // set previous cach as deleted for (FaceName &f : m_face_names.faces) if (f.texture_index == texture_index) { @@ -1805,12 +1818,9 @@ void GLGizmoEmboss::draw_font_preview(FaceName& face, bool is_visible) m_face_names.texture_index = texture_index; face.texture_index = texture_index; - // clear texture - - // render text to texture FontImageData data{ - text, + m_text, face.wx_name, m_face_names.encoding, m_face_names.texture_id, @@ -1827,9 +1837,18 @@ void GLGizmoEmboss::draw_font_preview(FaceName& face, bool is_visible) auto job = std::make_unique(std::move(data)); auto &worker = wxGetApp().plater()->get_ui_job_worker(); queue_job(worker, std::move(job)); + } else { + // cant start new thread at this moment so wait in queue + state_text = _u8L(" ... In queue"); + } + + if (!state_text.empty()) { + ImGui::SameLine(m_gui_cfg->face_name_texture_offset_x); + m_imgui->text(state_text); } ImGui::SameLine(m_gui_cfg->face_name_texture_offset_x); + ImTextureID tex_id = (void *) (intptr_t) m_face_names.texture_id; ImGui::Image(tex_id, size, uv0, uv1); } @@ -2674,7 +2693,6 @@ void GLGizmoEmboss::draw_style_edit() { ImGui::TextColored(ImGuiWrapper::COL_ORANGE_DARK, "%s", _u8L("WxFont is not loaded properly.").c_str()); return; } - bool exist_stored_style = m_style_manager.exist_stored_style(); bool exist_change_in_font = is_font_changed(m_style_manager); const GuiCfg::Translations &tr = m_gui_cfg->translations; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp index 2e6656ff7..d7e632b88 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp @@ -258,6 +258,7 @@ private: // protection for open too much font files together // Gtk:ERROR:../../../../gtk/gtkiconhelper.c:494:ensure_surface_for_gicon: assertion failed (error == NULL): Failed to load /usr/share/icons/Yaru/48x48/status/image-missing.png: Error opening file /usr/share/icons/Yaru/48x48/status/image-missing.png: Too many open files (g-io-error-quark, 31) + // This variable must exist until no CreateFontImageJob is running unsigned int count_opened_font_files = 0; // Configuration for texture height diff --git a/src/slic3r/GUI/Jobs/CreateFontNameImageJob.cpp b/src/slic3r/GUI/Jobs/CreateFontNameImageJob.cpp index 753dcdbfd..4057b730d 100644 --- a/src/slic3r/GUI/Jobs/CreateFontNameImageJob.cpp +++ b/src/slic3r/GUI/Jobs/CreateFontNameImageJob.cpp @@ -19,10 +19,11 @@ using namespace Slic3r; using namespace Slic3r::GUI; +const std::string CreateFontImageJob::default_text = "AaBbCc 123"; + CreateFontImageJob::CreateFontImageJob(FontImageData &&input) : m_input(std::move(input)) { - assert(!m_input.text.empty()); assert(wxFontEnumerator::IsValidFacename(m_input.font_name)); assert(m_input.gray_level > 0 && m_input.gray_level < 255); assert(m_input.texture_id != 0); @@ -41,9 +42,11 @@ void CreateFontImageJob::process(Ctl &ctl) if (font_file == nullptr) return; Emboss::FontFileWithCache font_file_with_cache(std::move(font_file)); - FontProp fp; // use only first line of text - std::string text = m_input.text; + std::string& text = m_input.text; + if (text.empty()) + text = default_text; // copy + size_t enter_pos = text.find('\n'); if (enter_pos < text.size()) { // text start with enter @@ -57,24 +60,39 @@ void CreateFontImageJob::process(Ctl &ctl) if (cancel->load()) return true; return false; }; + + FontProp fp; // create default font parameters ExPolygons shapes = Emboss::text2shapes(font_file_with_cache, text.c_str(), fp, was_canceled); + + // select some character from font e.g. default text + if (shapes.empty()) + shapes = Emboss::text2shapes(font_file_with_cache, default_text.c_str(), fp, was_canceled); + if (shapes.empty()) { + m_input.cancel->store(true); + return; + } + // normalize height of font BoundingBox bounding_box; for (ExPolygon &shape : shapes) bounding_box.merge(BoundingBox(shape.contour.points)); - if (bounding_box.size().x() < 1 || bounding_box.size().y() < 1) return; - double scale = m_input.size.y() / (double) bounding_box.size().y(); + if (bounding_box.size().x() < 1 || bounding_box.size().y() < 1) { + m_input.cancel->store(true); + return; + } + double scale = m_input.size.y() / (double) bounding_box.size().y(); BoundingBoxf bb2(bounding_box.min.cast(), bounding_box.max.cast()); bb2.scale(scale); Vec2d size_f = bb2.size(); - m_tex_size = Point(std::ceil(size_f.x()), std::ceil(size_f.y())); + m_tex_size = Point(std::ceil(size_f.x()), std::ceil(size_f.y())); // crop image width if (m_tex_size.x() > m_input.size.x()) m_tex_size.x() = m_input.size.x(); if (m_tex_size.y() > m_input.size.y()) m_tex_size.y() = m_input.size.y(); // Set up result - m_result = std::vector(m_tex_size.x() * m_tex_size.y() * 4, {255}); + unsigned bit_count = 4; // RGBA + m_result = std::vector(m_tex_size.x() * m_tex_size.y() * bit_count, {255}); sla::Resolution resolution(m_tex_size.x(), m_tex_size.y()); double pixel_dim = SCALING_FACTOR / scale; @@ -123,13 +141,17 @@ void CreateFontImageJob::finalize(bool canceled, std::exception_ptr &) const GLenum target = GL_TEXTURE_2D; glsafe(::glBindTexture(target, m_input.texture_id)); - GLint - w = m_tex_size.x(), h = m_tex_size.y(), - xoffset = m_input.size.x() - m_tex_size.x(), // arrange right - yoffset = m_input.size.y() * m_input.index; + GLsizei w = m_tex_size.x(), h = m_tex_size.y(); + GLint xoffset = m_input.size.x() - m_tex_size.x(), // arrange right + yoffset = m_input.size.y() * m_input.index; glsafe(::glTexSubImage2D(target, m_input.level, xoffset, yoffset, w, h, m_input.format, m_input.type, m_result.data())); + // clear rest of texture + std::vector empty_data(xoffset * h * 4, {0}); + glsafe(::glTexSubImage2D(target, m_input.level, 0, yoffset, xoffset, h, + m_input.format, m_input.type, empty_data.data())); + // bind default texture GLuint no_texture_id = 0; glsafe(::glBindTexture(target, no_texture_id)); diff --git a/src/slic3r/GUI/Jobs/CreateFontNameImageJob.hpp b/src/slic3r/GUI/Jobs/CreateFontNameImageJob.hpp index da96b2696..36c3e5e7f 100644 --- a/src/slic3r/GUI/Jobs/CreateFontNameImageJob.hpp +++ b/src/slic3r/GUI/Jobs/CreateFontNameImageJob.hpp @@ -68,6 +68,12 @@ public: /// /// void finalize(bool canceled, std::exception_ptr &) override; + + /// + /// Text used for generate preview for empty text + /// and when no glyph for given m_input.text + /// + static const std::string default_text; }; } // namespace Slic3r::GUI