More info for user in preview of font in combo box.

+ Clear rest of texture when short text is used
This commit is contained in:
Filip Sykala - NTB T15p 2023-01-10 08:36:33 +01:00
parent 09fc025cd5
commit 2b31fa7d4a
4 changed files with 73 additions and 26 deletions

View File

@ -1768,33 +1768,46 @@ void GLGizmoEmboss::init_font_name_texture() {
void GLGizmoEmboss::draw_font_preview(FaceName& face, bool is_visible) 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; 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()); ImVec2 size(m_gui_cfg->face_name_size.x(), m_gui_cfg->face_name_size.y());
// set to pixel 0,0 in texture float count_cached_textures_f = static_cast<float>(m_face_names.count_cached_textures);
ImVec2 uv0(0.f, 0.f), uv1(1.f / size.x, 1.f / size.y / m_face_names.count_cached_textures); std::string state_text;
ImTextureID tex_id = (void *) (intptr_t) m_face_names.texture_id; // 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) { if (face.is_created != nullptr) {
// not created preview
if (*face.is_created) { if (*face.is_created) {
// Already created preview
size_t texture_index = face.texture_index; size_t texture_index = face.texture_index;
uv0 = ImVec2(0.f, texture_index / (float) m_face_names.count_cached_textures), uv0 = ImVec2(0.f, texture_index / count_cached_textures_f);
uv1 = ImVec2(1.f, (texture_index + 1) / (float) m_face_names.count_cached_textures); uv1 = ImVec2(1.f, (texture_index + 1) / count_cached_textures_f);
} else if (!is_visible) { } 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.is_created = nullptr;
face.cancel->store(true); face.cancel->store(true);
} }
}
} else if (is_visible && count_opened_fonts < m_gui_cfg->max_count_opened_font_files) { } else if (is_visible && count_opened_fonts < m_gui_cfg->max_count_opened_font_files) {
++count_opened_fonts; ++count_opened_fonts;
face.cancel = std::make_shared<std::atomic_bool>(false); face.cancel = std::make_shared<std::atomic_bool>(false);
face.is_created = std::make_shared<bool>(false); face.is_created = std::make_shared<bool>(false);
std::string text = m_text.empty() ? "AaBbCc" : m_text;
const unsigned char gray_level = 5; const unsigned char gray_level = 5;
// format type and level must match to texture data // format type and level must match to texture data
const GLenum format = GL_RGBA, type = GL_UNSIGNED_BYTE; const GLenum format = GL_RGBA, type = GL_UNSIGNED_BYTE;
const GLint level = 0; const GLint level = 0;
// select next texture index // select next texture index
size_t texture_index = (m_face_names.texture_index + 1) % m_face_names.count_cached_textures; size_t texture_index = (m_face_names.texture_index + 1) % m_face_names.count_cached_textures;
// set previous cach as deleted // set previous cach as deleted
for (FaceName &f : m_face_names.faces) for (FaceName &f : m_face_names.faces)
if (f.texture_index == texture_index) { 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; m_face_names.texture_index = texture_index;
face.texture_index = texture_index; face.texture_index = texture_index;
// clear texture
// render text to texture // render text to texture
FontImageData data{ FontImageData data{
text, m_text,
face.wx_name, face.wx_name,
m_face_names.encoding, m_face_names.encoding,
m_face_names.texture_id, m_face_names.texture_id,
@ -1827,9 +1837,18 @@ void GLGizmoEmboss::draw_font_preview(FaceName& face, bool is_visible)
auto job = std::make_unique<CreateFontImageJob>(std::move(data)); auto job = std::make_unique<CreateFontImageJob>(std::move(data));
auto &worker = wxGetApp().plater()->get_ui_job_worker(); auto &worker = wxGetApp().plater()->get_ui_job_worker();
queue_job(worker, std::move(job)); 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); 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); 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()); ImGui::TextColored(ImGuiWrapper::COL_ORANGE_DARK, "%s", _u8L("WxFont is not loaded properly.").c_str());
return; return;
} }
bool exist_stored_style = m_style_manager.exist_stored_style(); bool exist_stored_style = m_style_manager.exist_stored_style();
bool exist_change_in_font = is_font_changed(m_style_manager); bool exist_change_in_font = is_font_changed(m_style_manager);
const GuiCfg::Translations &tr = m_gui_cfg->translations; const GuiCfg::Translations &tr = m_gui_cfg->translations;

View File

@ -258,6 +258,7 @@ private:
// protection for open too much font files together // 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) // 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; unsigned int count_opened_font_files = 0;
// Configuration for texture height // Configuration for texture height

View File

@ -19,10 +19,11 @@
using namespace Slic3r; using namespace Slic3r;
using namespace Slic3r::GUI; using namespace Slic3r::GUI;
const std::string CreateFontImageJob::default_text = "AaBbCc 123";
CreateFontImageJob::CreateFontImageJob(FontImageData &&input) CreateFontImageJob::CreateFontImageJob(FontImageData &&input)
: m_input(std::move(input)) : m_input(std::move(input))
{ {
assert(!m_input.text.empty());
assert(wxFontEnumerator::IsValidFacename(m_input.font_name)); assert(wxFontEnumerator::IsValidFacename(m_input.font_name));
assert(m_input.gray_level > 0 && m_input.gray_level < 255); assert(m_input.gray_level > 0 && m_input.gray_level < 255);
assert(m_input.texture_id != 0); assert(m_input.texture_id != 0);
@ -41,9 +42,11 @@ void CreateFontImageJob::process(Ctl &ctl)
if (font_file == nullptr) return; if (font_file == nullptr) return;
Emboss::FontFileWithCache font_file_with_cache(std::move(font_file)); Emboss::FontFileWithCache font_file_with_cache(std::move(font_file));
FontProp fp;
// use only first line of text // 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'); size_t enter_pos = text.find('\n');
if (enter_pos < text.size()) { if (enter_pos < text.size()) {
// text start with enter // text start with enter
@ -57,12 +60,26 @@ void CreateFontImageJob::process(Ctl &ctl)
if (cancel->load()) return true; if (cancel->load()) return true;
return false; return false;
}; };
FontProp fp; // create default font parameters
ExPolygons shapes = Emboss::text2shapes(font_file_with_cache, text.c_str(), fp, was_canceled); 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 // normalize height of font
BoundingBox bounding_box; BoundingBox bounding_box;
for (ExPolygon &shape : shapes) for (ExPolygon &shape : shapes)
bounding_box.merge(BoundingBox(shape.contour.points)); bounding_box.merge(BoundingBox(shape.contour.points));
if (bounding_box.size().x() < 1 || bounding_box.size().y() < 1) return; 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(); double scale = m_input.size.y() / (double) bounding_box.size().y();
BoundingBoxf bb2(bounding_box.min.cast<double>(), BoundingBoxf bb2(bounding_box.min.cast<double>(),
bounding_box.max.cast<double>()); bounding_box.max.cast<double>());
@ -74,7 +91,8 @@ void CreateFontImageJob::process(Ctl &ctl)
if (m_tex_size.y() > m_input.size.y()) m_tex_size.y() = m_input.size.y(); if (m_tex_size.y() > m_input.size.y()) m_tex_size.y() = m_input.size.y();
// Set up result // Set up result
m_result = std::vector<unsigned char>(m_tex_size.x() * m_tex_size.y() * 4, {255}); unsigned bit_count = 4; // RGBA
m_result = std::vector<unsigned char>(m_tex_size.x() * m_tex_size.y() * bit_count, {255});
sla::Resolution resolution(m_tex_size.x(), m_tex_size.y()); sla::Resolution resolution(m_tex_size.x(), m_tex_size.y());
double pixel_dim = SCALING_FACTOR / scale; double pixel_dim = SCALING_FACTOR / scale;
@ -123,13 +141,17 @@ void CreateFontImageJob::finalize(bool canceled, std::exception_ptr &)
const GLenum target = GL_TEXTURE_2D; const GLenum target = GL_TEXTURE_2D;
glsafe(::glBindTexture(target, m_input.texture_id)); glsafe(::glBindTexture(target, m_input.texture_id));
GLint GLsizei w = m_tex_size.x(), h = m_tex_size.y();
w = m_tex_size.x(), h = m_tex_size.y(), GLint xoffset = m_input.size.x() - m_tex_size.x(), // arrange right
xoffset = m_input.size.x() - m_tex_size.x(), // arrange right
yoffset = m_input.size.y() * m_input.index; yoffset = m_input.size.y() * m_input.index;
glsafe(::glTexSubImage2D(target, m_input.level, xoffset, yoffset, w, h, glsafe(::glTexSubImage2D(target, m_input.level, xoffset, yoffset, w, h,
m_input.format, m_input.type, m_result.data())); m_input.format, m_input.type, m_result.data()));
// clear rest of texture
std::vector<unsigned char> 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 // bind default texture
GLuint no_texture_id = 0; GLuint no_texture_id = 0;
glsafe(::glBindTexture(target, no_texture_id)); glsafe(::glBindTexture(target, no_texture_id));

View File

@ -68,6 +68,12 @@ public:
/// <param name="canceled"></param> /// <param name="canceled"></param>
/// <param name=""></param> /// <param name=""></param>
void finalize(bool canceled, std::exception_ptr &) override; void finalize(bool canceled, std::exception_ptr &) override;
/// <summary>
/// Text used for generate preview for empty text
/// and when no glyph for given m_input.text
/// </summary>
static const std::string default_text;
}; };
} // namespace Slic3r::GUI } // namespace Slic3r::GUI