mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-16 04:55:57 +08:00
Add cancel for generate face name texture preview job
This commit is contained in:
parent
1f1ed048db
commit
fb8de55d89
@ -128,7 +128,6 @@ GLGizmoEmboss::GLGizmoEmboss(GLCanvas3D &parent)
|
|||||||
, m_rotate_gizmo(parent, GLGizmoRotate::Axis::Z) // grab id = 2 (Z axis)
|
, m_rotate_gizmo(parent, GLGizmoRotate::Axis::Z) // grab id = 2 (Z axis)
|
||||||
, m_style_manager(m_imgui->get_glyph_ranges())
|
, m_style_manager(m_imgui->get_glyph_ranges())
|
||||||
, m_update_job_cancel(nullptr)
|
, m_update_job_cancel(nullptr)
|
||||||
, m_allow_update_rendered_font(false)
|
|
||||||
{
|
{
|
||||||
m_rotate_gizmo.set_group_id(0);
|
m_rotate_gizmo.set_group_id(0);
|
||||||
m_rotate_gizmo.set_using_local_coordinate(true);
|
m_rotate_gizmo.set_using_local_coordinate(true);
|
||||||
@ -1297,8 +1296,17 @@ void GLGizmoEmboss::init_face_names() {
|
|||||||
bool fixed_width_only = false;
|
bool fixed_width_only = false;
|
||||||
fontEnumerator.EnumerateFacenames(encoding, fixed_width_only);
|
fontEnumerator.EnumerateFacenames(encoding, fixed_width_only);
|
||||||
m_face_names.encoding = encoding;
|
m_face_names.encoding = encoding;
|
||||||
m_face_names.names = std::move(fontEnumerator.m_facenames);
|
std::vector<wxString> &names = fontEnumerator.m_facenames;
|
||||||
std::sort(m_face_names.names.begin(), m_face_names.names.end());
|
std::sort(names.begin(), names.end());
|
||||||
|
|
||||||
|
const float &width = m_gui_cfg->face_name_max_width;
|
||||||
|
m_face_names.faces.reserve(names.size());
|
||||||
|
for (const wxString &name : names) {
|
||||||
|
FaceName face_name = {name};
|
||||||
|
std::string name_str(name.ToUTF8().data());
|
||||||
|
face_name.name_truncated = ImGuiWrapper::trunc(name_str, width);
|
||||||
|
m_face_names.faces.push_back(std::move(face_name));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// create texture for visualization font face
|
// create texture for visualization font face
|
||||||
@ -1313,7 +1321,7 @@ void GLGizmoEmboss::init_font_name_texture() {
|
|||||||
glsafe(::glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
|
glsafe(::glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
|
||||||
glsafe(::glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
|
glsafe(::glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
|
||||||
const Vec2i &size = m_gui_cfg->face_name_size;
|
const Vec2i &size = m_gui_cfg->face_name_size;
|
||||||
GLint w = size.x(), h = m_face_names.names.size() * size.y();
|
GLint w = size.x(), h = m_face_names.faces.size() * size.y();
|
||||||
std::vector<unsigned char> data(4*w * h, {0});
|
std::vector<unsigned char> data(4*w * h, {0});
|
||||||
const GLenum format = GL_RGBA, type = GL_UNSIGNED_BYTE;
|
const GLenum format = GL_RGBA, type = GL_UNSIGNED_BYTE;
|
||||||
const GLint level = 0, internal_format = GL_RGBA, border = 0;
|
const GLint level = 0, internal_format = GL_RGBA, border = 0;
|
||||||
@ -1323,23 +1331,16 @@ void GLGizmoEmboss::init_font_name_texture() {
|
|||||||
GLuint no_texture_id = 0;
|
GLuint no_texture_id = 0;
|
||||||
glsafe(::glBindTexture(target, no_texture_id));
|
glsafe(::glBindTexture(target, no_texture_id));
|
||||||
|
|
||||||
// no one is initialized yet
|
// clear info about creation of texture - no one is initialized yet
|
||||||
m_face_names.exist_textures = std::vector<bool>(m_face_names.names.size(), {false});
|
for (FaceName &face : m_face_names.faces) {
|
||||||
|
face.cancel = nullptr;
|
||||||
|
face.is_created = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "slic3r/GUI/Jobs/CreateFontNameImageJob.hpp"
|
#include "slic3r/GUI/Jobs/CreateFontNameImageJob.hpp"
|
||||||
void GLGizmoEmboss::draw_font_list()
|
void GLGizmoEmboss::draw_font_list()
|
||||||
{
|
{
|
||||||
auto init_trancated_names = [&face_names = m_face_names,
|
|
||||||
width = m_gui_cfg->face_name_max_width]() {
|
|
||||||
if (!face_names.names_truncated.empty()) return;
|
|
||||||
face_names.names_truncated.reserve(face_names.names.size());
|
|
||||||
for (const wxString &face_name : face_names.names) {
|
|
||||||
std::string name(face_name.ToUTF8().data());
|
|
||||||
face_names.names_truncated.emplace_back(ImGuiWrapper::trunc(name, width));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Set partial
|
// Set partial
|
||||||
wxString actual_face_name;
|
wxString actual_face_name;
|
||||||
if (m_style_manager.is_activ_font()) {
|
if (m_style_manager.is_activ_font()) {
|
||||||
@ -1350,7 +1351,8 @@ void GLGizmoEmboss::draw_font_list()
|
|||||||
const char * selected = (!actual_face_name.empty()) ?
|
const char * selected = (!actual_face_name.empty()) ?
|
||||||
actual_face_name.ToUTF8().data() : " --- ";
|
actual_face_name.ToUTF8().data() : " --- ";
|
||||||
|
|
||||||
wxString del_facename;
|
std::optional<size_t> del_index;
|
||||||
|
|
||||||
ScopeGuard unknown_font_sc;
|
ScopeGuard unknown_font_sc;
|
||||||
if (m_is_unknown_font) {
|
if (m_is_unknown_font) {
|
||||||
m_imgui->disabled_end();
|
m_imgui->disabled_end();
|
||||||
@ -1358,38 +1360,50 @@ void GLGizmoEmboss::draw_font_list()
|
|||||||
m_imgui->disabled_begin(true);
|
m_imgui->disabled_begin(true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// variable for detection just closed combo box
|
||||||
|
static bool allow_update_rendered_font = false;
|
||||||
|
|
||||||
if (ImGui::BeginCombo("##font_selector", selected)) {
|
if (ImGui::BeginCombo("##font_selector", selected)) {
|
||||||
if (!m_face_names.is_init) init_face_names();
|
if (!m_face_names.is_init) init_face_names();
|
||||||
init_font_name_texture();
|
if (m_face_names.texture_id == 0) init_font_name_texture();
|
||||||
if (m_face_names.names_truncated.empty()) init_trancated_names();
|
|
||||||
ImTextureID tex_id = (void *) (intptr_t) m_face_names.texture_id;
|
ImTextureID tex_id = (void *) (intptr_t) m_face_names.texture_id;
|
||||||
for (const wxString &face_name : m_face_names.names) {
|
unsigned int &count_opened_fonts = m_face_names.count_opened_font_files;
|
||||||
size_t index = &face_name - &m_face_names.names.front();
|
for (FaceName &face : m_face_names.faces) {
|
||||||
|
const wxString &face_name = face.name;
|
||||||
|
size_t index = &face - &m_face_names.faces.front();
|
||||||
ImGui::PushID(index);
|
ImGui::PushID(index);
|
||||||
bool is_selected = (actual_face_name == face_name);
|
bool is_selected = (actual_face_name == face_name);
|
||||||
ImVec2 selectable_size(0, m_gui_cfg->face_name_size.y());
|
ImVec2 selectable_size(0, m_gui_cfg->face_name_size.y());
|
||||||
ImGuiSelectableFlags flags = 0;
|
ImGuiSelectableFlags flags = 0;
|
||||||
if (ImGui::Selectable(m_face_names.names_truncated[index].c_str(),
|
if (ImGui::Selectable(face.name_truncated.c_str(), is_selected, flags, selectable_size)) {
|
||||||
is_selected, flags, selectable_size)) {
|
|
||||||
if (!select_facename(face_name)) {
|
if (!select_facename(face_name)) {
|
||||||
del_facename = face_name;
|
del_index = index;
|
||||||
wxMessageBox(GUI::format(
|
wxMessageBox(GUI::format(_L("Font face \"%1%\" can't be selected."), face_name));
|
||||||
_L("Font face \"%1%\" can't be selected."), face_name));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ImGui::IsItemHovered())
|
if (ImGui::IsItemHovered())
|
||||||
ImGui::SetTooltip("%s", face_name.ToUTF8().data());
|
ImGui::SetTooltip("%s", face_name.ToUTF8().data());
|
||||||
if (is_selected) ImGui::SetItemDefaultFocus();
|
if (is_selected) ImGui::SetItemDefaultFocus();
|
||||||
if (m_face_names.exist_textures[index]) {
|
|
||||||
ImGui::SameLine(m_gui_cfg->face_name_max_width);
|
if (face.is_created != nullptr){
|
||||||
ImVec2 size(m_gui_cfg->face_name_size.x(),
|
if (*face.is_created){
|
||||||
m_gui_cfg->face_name_size.y()),
|
ImGui::SameLine(m_gui_cfg->face_name_max_width);
|
||||||
uv0(0.f, index / (float) m_face_names.names.size()),
|
ImVec2 size(m_gui_cfg->face_name_size.x(),
|
||||||
uv1(1.f, (index + 1) / (float) m_face_names.names.size());
|
m_gui_cfg->face_name_size.y()),
|
||||||
ImGui::Image(tex_id, size, uv0, uv1);
|
uv0(0.f, index / (float) m_face_names.faces.size()),
|
||||||
} else if (ImGui::IsItemVisible() && m_count_opened_font_files < 10) {
|
uv1(1.f, (index + 1) / (float) m_face_names.faces.size());
|
||||||
++m_count_opened_font_files;
|
ImGui::Image(tex_id, size, uv0, uv1);
|
||||||
m_face_names.exist_textures[index] = true;
|
} else if (!ImGui::IsItemVisible()) {
|
||||||
|
face.cancel->store(true);
|
||||||
|
face.is_created = nullptr;
|
||||||
|
}
|
||||||
|
} else if (ImGui::IsItemVisible() &&
|
||||||
|
count_opened_fonts < m_gui_cfg->max_count_opened_font_files) {
|
||||||
|
++count_opened_fonts;
|
||||||
|
face.cancel = std::make_shared<std::atomic_bool>(false);
|
||||||
|
face.is_created = std::make_shared<bool>(false);
|
||||||
|
|
||||||
std::string text = m_text.empty() ? "AaBbCc" : m_text;
|
std::string text = m_text.empty() ? "AaBbCc" : m_text;
|
||||||
|
|
||||||
const unsigned char gray_level = 5;
|
const unsigned char gray_level = 5;
|
||||||
@ -1403,12 +1417,14 @@ void GLGizmoEmboss::draw_font_list()
|
|||||||
m_face_names.texture_id,
|
m_face_names.texture_id,
|
||||||
index,
|
index,
|
||||||
m_gui_cfg->face_name_size,
|
m_gui_cfg->face_name_size,
|
||||||
&m_allow_update_rendered_font,
|
|
||||||
gray_level,
|
gray_level,
|
||||||
format,
|
format,
|
||||||
type,
|
type,
|
||||||
level,
|
level,
|
||||||
&m_count_opened_font_files };
|
&count_opened_fonts,
|
||||||
|
face.cancel, // copy
|
||||||
|
face.is_created // copy
|
||||||
|
};
|
||||||
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));
|
||||||
@ -1421,20 +1437,21 @@ void GLGizmoEmboss::draw_font_list()
|
|||||||
static_cast<int>(m_face_names.names.size()));
|
static_cast<int>(m_face_names.names.size()));
|
||||||
#endif // SHOW_FONT_COUNT
|
#endif // SHOW_FONT_COUNT
|
||||||
ImGui::EndCombo();
|
ImGui::EndCombo();
|
||||||
m_allow_update_rendered_font = true;
|
allow_update_rendered_font = true;
|
||||||
} else if (m_allow_update_rendered_font) {
|
} else if (allow_update_rendered_font) {
|
||||||
// free texture and set id to zero
|
// free texture and set id to zero
|
||||||
m_allow_update_rendered_font = false;
|
allow_update_rendered_font = false;
|
||||||
|
// cancel all process for generation of texture
|
||||||
|
for (FaceName &face : m_face_names.faces)
|
||||||
|
if (face.cancel != nullptr) face.cancel->store(true);
|
||||||
glsafe(::glDeleteTextures(1, &m_face_names.texture_id));
|
glsafe(::glDeleteTextures(1, &m_face_names.texture_id));
|
||||||
m_face_names.texture_id = 0;
|
m_face_names.texture_id = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete unloadable face name when appear
|
// delete unloadable face name when appear
|
||||||
if (!del_facename.empty()) {
|
if (del_index.has_value()) {
|
||||||
// IMPROVE: store list of deleted facename into app.ini
|
// IMPROVE: store list of deleted facename into app.ini
|
||||||
std::vector<wxString> &f = m_face_names.names;
|
m_face_names.faces.erase(m_face_names.faces.begin() + (*del_index));
|
||||||
f.erase(std::remove(f.begin(), f.end(), del_facename), f.end());
|
|
||||||
m_face_names.names_truncated.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ALLOW_ADD_FONT_BY_FILE
|
#ifdef ALLOW_ADD_FONT_BY_FILE
|
||||||
|
@ -192,6 +192,9 @@ private:
|
|||||||
Vec2i face_name_size = Vec2i(100, 0);
|
Vec2i face_name_size = Vec2i(100, 0);
|
||||||
float face_name_max_width = 100.f;
|
float face_name_max_width = 100.f;
|
||||||
|
|
||||||
|
// maximal texture generate jobs running at once
|
||||||
|
unsigned int max_count_opened_font_files = 10;
|
||||||
|
|
||||||
// Only translations needed for calc GUI size
|
// Only translations needed for calc GUI size
|
||||||
struct Translations
|
struct Translations
|
||||||
{
|
{
|
||||||
@ -222,17 +225,32 @@ private:
|
|||||||
|
|
||||||
EmbossStyleManager m_style_manager;
|
EmbossStyleManager m_style_manager;
|
||||||
|
|
||||||
|
struct FaceName{
|
||||||
|
wxString name;
|
||||||
|
std::string name_truncated = "";
|
||||||
|
|
||||||
|
// State for generation of texture
|
||||||
|
// when start generate create share pointers
|
||||||
|
std::shared_ptr<std::atomic<bool>> cancel = nullptr;
|
||||||
|
// R/W only on main thread - finalize of job
|
||||||
|
std::shared_ptr<bool> is_created = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
// Keep sorted list of loadable face names
|
// Keep sorted list of loadable face names
|
||||||
struct Facenames
|
struct Facenames
|
||||||
{
|
{
|
||||||
bool is_init = false;
|
// flag if face names was enumerated from OS
|
||||||
std::vector<wxString> names;
|
bool is_init = false;
|
||||||
wxFontEncoding encoding;
|
|
||||||
|
|
||||||
std::vector<std::string> names_truncated;
|
wxFontEncoding encoding;
|
||||||
GLuint texture_id = 0;
|
std::vector<FaceName> faces;
|
||||||
// is texture started create?
|
|
||||||
std::vector<bool> exist_textures = {};
|
// Identify if preview texture exists
|
||||||
|
GLuint texture_id = 0;
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
unsigned int count_opened_font_files = 0;
|
||||||
} m_face_names;
|
} m_face_names;
|
||||||
|
|
||||||
// Text to emboss
|
// Text to emboss
|
||||||
@ -257,12 +275,6 @@ private:
|
|||||||
// cancel for previous update of volume to cancel finalize part
|
// cancel for previous update of volume to cancel finalize part
|
||||||
std::shared_ptr<std::atomic<bool>> m_update_job_cancel;
|
std::shared_ptr<std::atomic<bool>> m_update_job_cancel;
|
||||||
|
|
||||||
// cancel for rendering font name after close comboBox
|
|
||||||
bool m_allow_update_rendered_font;
|
|
||||||
// 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)
|
|
||||||
unsigned int m_count_opened_font_files = 0;
|
|
||||||
|
|
||||||
// Rotation gizmo
|
// Rotation gizmo
|
||||||
GLGizmoRotate m_rotate_gizmo;
|
GLGizmoRotate m_rotate_gizmo;
|
||||||
// Value is set only when dragging rotation to calculate actual angle
|
// Value is set only when dragging rotation to calculate actual angle
|
||||||
|
@ -45,7 +45,11 @@ void CreateFontImageJob::process(Ctl &ctl)
|
|||||||
text = text.substr(0, enter_pos);
|
text = text.substr(0, enter_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::function<bool()> was_canceled = [&ctl]() -> bool { return ctl.was_canceled(); };
|
std::function<bool()> was_canceled = [&ctl, cancel = m_input.cancel]() -> bool {
|
||||||
|
if (ctl.was_canceled()) return true;
|
||||||
|
if (cancel->load()) return true;
|
||||||
|
return false;
|
||||||
|
};
|
||||||
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);
|
||||||
// normalize height of font
|
// normalize height of font
|
||||||
BoundingBox bounding_box;
|
BoundingBox bounding_box;
|
||||||
@ -96,8 +100,9 @@ void CreateFontImageJob::finalize(bool canceled, std::exception_ptr &)
|
|||||||
{
|
{
|
||||||
if (m_input.count_opened_font_files)
|
if (m_input.count_opened_font_files)
|
||||||
--(*m_input.count_opened_font_files);
|
--(*m_input.count_opened_font_files);
|
||||||
if (canceled) return;
|
if (canceled || m_input.cancel->load()) return;
|
||||||
if (! (* m_input.allow_update)) return;
|
|
||||||
|
*m_input.is_created = true;
|
||||||
|
|
||||||
// upload texture on GPU
|
// upload texture on GPU
|
||||||
const GLenum target = GL_TEXTURE_2D;
|
const GLenum target = GL_TEXTURE_2D;
|
||||||
|
@ -29,9 +29,6 @@ struct FontImageData
|
|||||||
// And Limit for width
|
// And Limit for width
|
||||||
Vec2i size; // in px
|
Vec2i size; // in px
|
||||||
|
|
||||||
// cancel, can be used only in finalize
|
|
||||||
bool *allow_update;
|
|
||||||
|
|
||||||
// bigger value create darker image
|
// bigger value create darker image
|
||||||
// divide value 255
|
// divide value 255
|
||||||
unsigned char gray_level = 5;
|
unsigned char gray_level = 5;
|
||||||
@ -43,6 +40,9 @@ struct FontImageData
|
|||||||
// prevent opening too much files
|
// prevent opening too much files
|
||||||
// it is decreased in finalize phase
|
// it is decreased in finalize phase
|
||||||
unsigned int *count_opened_font_files = nullptr;
|
unsigned int *count_opened_font_files = nullptr;
|
||||||
|
|
||||||
|
std::shared_ptr<std::atomic<bool>> cancel = nullptr;
|
||||||
|
std::shared_ptr<bool> is_created = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user