diff --git a/src/libslic3r/Emboss.cpp b/src/libslic3r/Emboss.cpp index 7c4d93661c..70d614e98c 100644 --- a/src/libslic3r/Emboss.cpp +++ b/src/libslic3r/Emboss.cpp @@ -24,9 +24,8 @@ public: static std::optional load_font_info(const Emboss::FontFile &font); static std::optional load_font_info(const unsigned char *data, unsigned int index = 0); - static std::optional get_glyph(stbtt_fontinfo &font_info, int unicode_letter, float flatness); - static std::optional get_glyph(int unicode, const Emboss::FontFile &font, const FontProp &font_prop, - Emboss::Glyphs &cache, std::optional &font_info_opt); + static std::optional get_glyph(const stbtt_fontinfo &font_info, int unicode_letter, float flatness); + static std::optional get_glyph(int unicode, const Emboss::FontFile &font, const FontProp &font_prop, std::optional &font_info_opt); static FontItem create_font_item(std::wstring name, std::wstring path); @@ -63,7 +62,7 @@ std::optional Private::load_font_info( return font_info; } -std::optional Private::get_glyph(stbtt_fontinfo &font_info, int unicode_letter, float flatness) +std::optional Private::get_glyph(const stbtt_fontinfo &font_info, int unicode_letter, float flatness) { int glyph_index = stbtt_FindGlyphIndex(&font_info, unicode_letter); if (glyph_index == 0) { @@ -128,13 +127,9 @@ std::optional Private::get_glyph( int unicode, const Emboss::FontFile & font, const FontProp & font_prop, - Emboss::Glyphs & cache, std::optional &font_info_opt) { const double RESOLUTION = 0.0125; // TODO: read from printer configuration - auto glyph_item = cache.find(unicode); - if (glyph_item != cache.end()) - return glyph_item->second; if (!font_info_opt.has_value()) { font_info_opt = Private::load_font_info(font); @@ -182,8 +177,6 @@ std::optional Private::get_glyph( // unify multipoints with similar position. Could appear after union dilate_to_unique_points(glyph_opt->shape); - cache[unicode] = *glyph_opt; - return glyph_opt; } @@ -593,7 +586,7 @@ std::optional Emboss::letter2glyph(const FontFile &font, return Private::get_glyph(*font_info_opt, letter, flatness); } -ExPolygons Emboss::text2shapes(FontFile & font, +ExPolygons Emboss::text2shapes(const FontFile &font, const char * text, const FontProp &font_prop) { @@ -617,14 +610,26 @@ ExPolygons Emboss::text2shapes(FontFile & font, if (wc == '\t') { // '\t' = 4*space => same as imgui const int count_spaces = 4; - std::optional space_opt = Private::get_glyph(int(' '), font, font_prop, font.cache, font_info_opt); + auto space = int(' '); + std::optional space_opt = font.get_glyph(space); + if (! space_opt) { + space_opt = Private::get_glyph(space, font, font_prop, font_info_opt); + if (space_opt) + font.cache_glyph(space, *space_opt); + } if (!space_opt.has_value()) continue; cursor.x() += count_spaces * space_opt->advance_width; continue; } int unicode = static_cast(wc); - std::optional glyph_opt = Private::get_glyph(unicode, font, font_prop, font.cache, font_info_opt); + std::optional glyph_opt = font.get_glyph(unicode); + if (! glyph_opt) { + glyph_opt = Private::get_glyph(unicode, font, font_prop, font_info_opt); + if (glyph_opt) + font.cache_glyph(unicode, *glyph_opt); + } + if (!glyph_opt.has_value()) continue; // move glyph to cursor position @@ -652,7 +657,7 @@ void Emboss::apply_transformation(const FontProp &font_prop, } } -bool Emboss::is_italic(FontFile &font) { +bool Emboss::is_italic(const FontFile &font) { std::optional font_info_opt = Private::load_font_info(font); @@ -814,3 +819,32 @@ Transform3d Emboss::create_transformation_onto_surface(const Vec3f &position, transform.rotate(up_rot); return transform; } + +static std::mutex FontFile_cache_mutex; + +std::optional Emboss::FontFile::get_glyph(int unicode) const +{ + std::lock_guard guard(FontFile_cache_mutex); + auto glyph_item = m_cache.find(unicode); + if (glyph_item != m_cache.end()) + return glyph_item->second; + return {}; +} + +void Emboss::FontFile::cache_glyph(int unicode, Emboss::Glyph glyph) const +{ + std::lock_guard guard(FontFile_cache_mutex); + m_cache[unicode] = std::move(glyph); +} + +void Emboss::FontFile::clear_glyph_cache() const +{ + std::lock_guard guard(FontFile_cache_mutex); + m_cache.clear(); +} + +size_t Emboss::FontFile::glyph_cache_size() const +{ + std::lock_guard guard(FontFile_cache_mutex); + return m_cache.size(); +} \ No newline at end of file diff --git a/src/libslic3r/Emboss.hpp b/src/libslic3r/Emboss.hpp index 69c2893a6a..4e8e1ebf1b 100644 --- a/src/libslic3r/Emboss.hpp +++ b/src/libslic3r/Emboss.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include // indexed_triangle_set #include "Polygon.hpp" #include "ExPolygon.hpp" @@ -75,8 +76,6 @@ public: // for convert font units to pixel int unit_per_em; - Emboss::Glyphs cache; // cache of glyphs - FontFile(std::vector &&buffer, unsigned int count, int ascent, @@ -97,6 +96,17 @@ public: buffer.size() == other.buffer.size() && buffer == other.buffer; } + + std::optional get_glyph(int unicode) const; + // These two methods modifying cache are marked as const, because their + // access to the cache is guarded by a global mutex specific to all FontFile instances. + void cache_glyph(int unicode, Emboss::Glyph glyph) const; + void clear_glyph_cache() const; + size_t glyph_cache_size() const; + + private: + // Cache of glyphs, guarded by a global mutex specific to all FontFile instances. + mutable Emboss::Glyphs m_cache; }; /// @@ -130,7 +140,7 @@ public: /// Characters to convert /// User defined property of the font /// Inner polygon cw(outer ccw) - static ExPolygons text2shapes(FontFile & font, + static ExPolygons text2shapes(const FontFile &font, const char * text, const FontProp &font_prop); @@ -149,7 +159,7 @@ public: /// /// Selector of font /// True when the font description contains italic/obligue otherwise False - static bool is_italic(FontFile &font); + static bool is_italic(const FontFile &font); /// /// Project 2d point into space diff --git a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp index c6b8157071..55dc5e4085 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp @@ -662,7 +662,7 @@ bool GLGizmoEmboss::process() if (m_volume == nullptr) return false; // exist loaded font? - std::shared_ptr& font_file = m_font_manager.get_font_file(); + std::shared_ptr& font_file = m_font_manager.get_font_file(); if (font_file == nullptr) return false; auto data = std::make_unique(font_file, create_configuration(), @@ -1224,7 +1224,7 @@ void GLGizmoEmboss::draw_style_list() { bool GLGizmoEmboss::italic_button() { std::optional &wx_font = m_font_manager.get_wx_font(); - std::shared_ptr &font_file = m_font_manager.get_font_file(); + std::shared_ptr &font_file = m_font_manager.get_font_file(); if (!wx_font.has_value() || font_file == nullptr) { draw_icon(IconType::italic, IconState::disabled); return false; @@ -1266,7 +1266,7 @@ bool GLGizmoEmboss::italic_button() bool GLGizmoEmboss::bold_button() { std::optional &wx_font = m_font_manager.get_wx_font(); - std::shared_ptr &font_file = m_font_manager.get_font_file(); + std::shared_ptr &font_file = m_font_manager.get_font_file(); if (!wx_font.has_value() || font_file==nullptr) { draw_icon(IconType::bold, IconState::disabled); return false; @@ -1576,7 +1576,7 @@ void GLGizmoEmboss::do_rotate(float relative_z_angle) void GLGizmoEmboss::draw_advanced() { - std::shared_ptr& font_file = m_font_manager.get_font_file(); + std::shared_ptr& font_file = m_font_manager.get_font_file(); if (font_file == nullptr) { ImGui::Text("%s", _u8L("Advanced font options could be change only for corect font.\nStart with select correct font.").c_str()); return; @@ -1589,7 +1589,7 @@ void GLGizmoEmboss::draw_advanced() ", descent=" + std::to_string(font_file->descent) + ", lineGap=" + std::to_string(font_file->linegap) + ", unitPerEm=" + std::to_string(font_file->unit_per_em) + - ", cache(" + std::to_string(font_file->cache.size()) + " glyphs)"; + ", cache(" + std::to_string(font_file->glyph_cache_size()) + " glyphs)"; if (font_file->count > 1) ff_property += ", collect=" + std::to_string(font_file->index + 1) + "/" + std::to_string(font_file->count); m_imgui->text_colored(ImGuiWrapper::COL_GREY_DARK, ff_property); @@ -1698,7 +1698,8 @@ void GLGizmoEmboss::draw_advanced() ImGui::PushID(1 << (10 + i)); bool is_selected = i == font_file->index; if (ImGui::Selectable(std::to_string(i).c_str(), is_selected)) { - font_file->index = i; +//FIXME change true type font index in collection atomically, by duplicating the font! +// font_file->index = i; exist_change = true; } ImGui::PopID(); diff --git a/src/slic3r/GUI/Jobs/EmbossJob.cpp b/src/slic3r/GUI/Jobs/EmbossJob.cpp index a2edc15811..a4a4eeec05 100644 --- a/src/slic3r/GUI/Jobs/EmbossJob.cpp +++ b/src/slic3r/GUI/Jobs/EmbossJob.cpp @@ -240,10 +240,10 @@ TriangleMesh EmbossCreateJob::create_default_mesh() return triangle_mesh; } -TriangleMesh EmbossCreateJob::create_mesh(const char * text, - Emboss::FontFile &font, - const FontProp & font_prop, - Ctl & ctl) +TriangleMesh EmbossCreateJob::create_mesh(const char * text, + const Emboss::FontFile &font, + const FontProp & font_prop, + Ctl & ctl) { ExPolygons shapes = Emboss::text2shapes(font, text, font_prop); if (shapes.empty()) return {}; diff --git a/src/slic3r/GUI/Jobs/EmbossJob.hpp b/src/slic3r/GUI/Jobs/EmbossJob.hpp index 37dd757a65..6ce35f4975 100644 --- a/src/slic3r/GUI/Jobs/EmbossJob.hpp +++ b/src/slic3r/GUI/Jobs/EmbossJob.hpp @@ -46,10 +46,10 @@ public: /// Property of font /// Control for job, check of cancelation /// Triangle mesh model - static TriangleMesh create_mesh(const char * text, - Emboss::FontFile &font, - const FontProp & font_prop, - Ctl & ctl); + static TriangleMesh create_mesh(const char * text, + const Emboss::FontFile &font, + const FontProp & font_prop, + Ctl & ctl); private: static TriangleMesh create_default_mesh(); @@ -62,14 +62,14 @@ private: struct EmbossDataBase { // Pointer on Data of font (glyph shapes) - std::shared_ptr font_file; + std::shared_ptr font_file; // font item is not used for create object TextConfiguration text_configuration; // new volume name created from text std::string volume_name; - EmbossDataBase(std::shared_ptr font_file, - TextConfiguration text_configuration, - std::string volume_name) + EmbossDataBase(std::shared_ptr font_file, + TextConfiguration text_configuration, + std::string volume_name) : font_file(std::move(font_file)) , text_configuration(text_configuration) , volume_name(volume_name) @@ -88,10 +88,10 @@ struct EmbossDataUpdate : public EmbossDataBase // unique identifier of volume to change // Change of volume change id, last change could disapear // ObjectID volume_id; - EmbossDataUpdate(std::shared_ptr font_file, - TextConfiguration text_configuration, - std::string volume_name, - ModelVolume * volume) + EmbossDataUpdate(std::shared_ptr font_file, + TextConfiguration text_configuration, + std::string volume_name, + ModelVolume * volume) : EmbossDataBase(std::move(font_file), text_configuration, volume_name) , volume(volume) {} @@ -125,7 +125,7 @@ struct EmbossDataCreate: public EmbossDataBase // It is inside of GLGizmoEmboss object, // so I hope it will survive - EmbossDataCreate(std::shared_ptr font_file, + EmbossDataCreate(std::shared_ptr font_file, const TextConfiguration & text_configuration, const std::string & volume_name, ModelVolumeType volume_type, diff --git a/src/slic3r/Utils/FontManager.cpp b/src/slic3r/Utils/FontManager.cpp index b056b62c92..9d4eb86d05 100644 --- a/src/slic3r/Utils/FontManager.cpp +++ b/src/slic3r/Utils/FontManager.cpp @@ -146,7 +146,7 @@ void FontManager::add_fonts(FontList font_list) add_font(fi); } -std::shared_ptr &FontManager::get_font_file() +std::shared_ptr &FontManager::get_font_file() { // TODO: fix not selected font //if (!is_activ_font()) return nullptr; @@ -367,7 +367,7 @@ void FontManager::create_texture(size_t index, const std::string &text, GLuint& if (index >= m_font_list.size()) return; Item &item = m_font_list[index]; const FontProp &font_prop = item.font_item.prop; - std::shared_ptr &font_file = item.font_file; + std::shared_ptr &font_file = item.font_file; if (font_file == nullptr && !set_up_font_file(index)) return; ExPolygons shapes = Emboss::text2shapes(*font_file, text.c_str(), font_prop); @@ -415,7 +415,7 @@ void FontManager::init_style_images(int max_width) { for (Item &item : m_font_list) { FontItem & font_item = item.font_item; const FontProp & font_prop = font_item.prop; - std::shared_ptr &font_file = item.font_file; + std::shared_ptr &font_file = item.font_file; size_t index = &item - &m_font_list.front(); if (font_file == nullptr && !set_up_font_file(index)) continue; if (font_file == nullptr) continue; @@ -520,10 +520,10 @@ void FontManager::init_style_images(int max_width) { void FontManager::free_style_images() { if (!is_activ_font()) return; - std::shared_ptr &font_file = + std::shared_ptr &font_file = m_font_list[m_font_selected].font_file; - if(font_file != nullptr) - font_file->cache.clear(); + if (font_file != nullptr) + font_file->clear_glyph_cache(); if (!m_exist_style_images) return; GLuint tex_id = (GLuint) (intptr_t) m_font_list.front().image->texture_id; diff --git a/src/slic3r/Utils/FontManager.hpp b/src/slic3r/Utils/FontManager.hpp index a0b75c51f3..450c2af7bd 100644 --- a/src/slic3r/Utils/FontManager.hpp +++ b/src/slic3r/Utils/FontManager.hpp @@ -72,7 +72,7 @@ public: void add_fonts(FontList font_list); // getter on active font file for access to glyphs - std::shared_ptr &get_font_file(); + std::shared_ptr &get_font_file(); // getter on active font item for access to font property const FontItem &get_font_item() const; @@ -137,7 +137,7 @@ public: std::string truncated_name; // share font file data with emboss job thread - std::shared_ptr font_file = nullptr; + std::shared_ptr font_file; std::optional imgui_font_index;