Separate actual style from styles

(save button will save only actual style no others)
This commit is contained in:
Filip Sykala - NTB T15p 2022-07-29 09:06:20 +02:00
parent e9d65da046
commit f7eef00abb
6 changed files with 582 additions and 666 deletions

File diff suppressed because it is too large Load Diff

View File

@ -32,6 +32,7 @@ namespace Slic3r{
namespace Slic3r::GUI { namespace Slic3r::GUI {
class MeshRaycaster; class MeshRaycaster;
struct EmbossDataBase;
class GLGizmoEmboss : public GLGizmoBase class GLGizmoEmboss : public GLGizmoBase
{ {
@ -121,18 +122,18 @@ private:
/// TODO: make more general, static and move to ImGuiWrapper /// TODO: make more general, static and move to ImGuiWrapper
/// </summary> /// </summary>
/// <returns>True when value changed otherwise FALSE.</returns> /// <returns>True when value changed otherwise FALSE.</returns>
bool rev_input(const std::string &name, float &value, float *default_value, bool rev_input(const std::string &name, float &value, const float *default_value,
const std::string &undo_tooltip, float step, float step_fast, const char *format, const std::string &undo_tooltip, float step, float step_fast, const char *format,
ImGuiInputTextFlags flags = 0); ImGuiInputTextFlags flags = 0);
bool rev_checkbox(const std::string &name, bool &value, bool* default_value, const std::string &undo_tooltip); bool rev_checkbox(const std::string &name, bool &value, const bool* default_value, const std::string &undo_tooltip);
bool rev_slider(const std::string &name, std::optional<int>& value, std::optional<int> *default_value, bool rev_slider(const std::string &name, std::optional<int>& value, const std::optional<int> *default_value,
const std::string &undo_tooltip, int v_min, int v_max, const std::string &format, const wxString &tooltip); const std::string &undo_tooltip, int v_min, int v_max, const std::string &format, const wxString &tooltip);
bool rev_slider(const std::string &name, std::optional<float>& value, std::optional<float> *default_value, bool rev_slider(const std::string &name, std::optional<float>& value, const std::optional<float> *default_value,
const std::string &undo_tooltip, float v_min, float v_max, const std::string &format, const wxString &tooltip); const std::string &undo_tooltip, float v_min, float v_max, const std::string &format, const wxString &tooltip);
bool rev_slider(const std::string &name, float &value, float *default_value, bool rev_slider(const std::string &name, float &value, const float *default_value,
const std::string &undo_tooltip, float v_min, float v_max, const std::string &format, const wxString &tooltip); const std::string &undo_tooltip, float v_min, float v_max, const std::string &format, const wxString &tooltip);
template<typename T, typename Draw> template<typename T, typename Draw>
bool revertible(const std::string &name, T &value, T *default_value, const std::string &undo_tooltip, float undo_offset, Draw draw); bool revertible(const std::string &name, T &value, const T *default_value, const std::string &undo_tooltip, float undo_offset, Draw draw);
void set_minimal_window_size(bool is_advance_edit_style); void set_minimal_window_size(bool is_advance_edit_style);
const ImVec2 &get_minimal_window_size() const; const ImVec2 &get_minimal_window_size() const;
@ -145,8 +146,8 @@ private:
bool choose_true_type_file(); bool choose_true_type_file();
bool choose_svg_file(); bool choose_svg_file();
// Create object described how to make a Volume // prepare base data for emboss text
TextConfiguration create_configuration(); EmbossDataBase create_emboss_data_base();
bool load_configuration(ModelVolume *volume); bool load_configuration(ModelVolume *volume);
// Create notification when unknown font type is used // Create notification when unknown font type is used
@ -154,8 +155,6 @@ private:
void create_notification_not_valid_font(const TextConfiguration& tc); void create_notification_not_valid_font(const TextConfiguration& tc);
void remove_notification_not_valid_font(); void remove_notification_not_valid_font();
std::string create_volume_name();
// This configs holds GUI layout size given by translated texts. // This configs holds GUI layout size given by translated texts.
// etc. When language changes, GUI is recreated and this class constructed again, // etc. When language changes, GUI is recreated and this class constructed again,
// so the change takes effect. (info by GLGizmoFdmSupports.hpp) // so the change takes effect. (info by GLGizmoFdmSupports.hpp)
@ -212,7 +211,7 @@ private:
std::optional<ImVec2> m_set_window_offset; std::optional<ImVec2> m_set_window_offset;
bool m_is_advanced_edit_style = false; bool m_is_advanced_edit_style = false;
FontManager m_font_manager; FontManager m_style_manager;
// Keep sorted list of loadable face names // Keep sorted list of loadable face names
struct Facenames struct Facenames
@ -227,15 +226,12 @@ private:
std::vector<bool> exist_textures = {}; std::vector<bool> exist_textures = {};
} m_face_names; } m_face_names;
// Track stored values in AppConfig
std::optional<FontItem> m_stored_font_item;
std::optional<wxFont> m_stored_wx_font; // cache for stored wx font to not create every frame
std::map<std::string, FontItem> m_stored_font_items;
void fill_stored_font_items();
void select_stored_font_item();
// Text to emboss // Text to emboss
std::string m_text; std::string m_text;
// actual volume
ModelVolume *m_volume;
// True when m_text contain character unknown by selected font // True when m_text contain character unknown by selected font
bool m_text_contain_unknown_glyph = false; bool m_text_contain_unknown_glyph = false;
@ -245,9 +241,6 @@ private:
// cancel for rendering font name // cancel for rendering font name
bool m_allow_update_rendered_font; bool m_allow_update_rendered_font;
// actual volume
ModelVolume *m_volume;
// Rotation gizmo // Rotation gizmo
GLGizmoRotate m_rotate_gizmo; GLGizmoRotate m_rotate_gizmo;
@ -290,11 +283,6 @@ private:
bool draw_clickable(IconType icon, IconState state, IconType hover_icon, IconState hover_state); bool draw_clickable(IconType icon, IconState state, IconType hover_icon, IconState hover_state);
bool draw_button(IconType icon, bool disable = false); bool draw_button(IconType icon, bool disable = false);
// load / store appConfig
static FontList load_font_list_from_app_config(const AppConfig *cfg, size_t &activ_font_index);
void store_font_list_to_app_config();
//void store_font_item_to_app_config() const;
// only temporary solution // only temporary solution
static const std::string M_ICON_FILENAME; static const std::string M_ICON_FILENAME;

View File

@ -19,6 +19,8 @@ const std::string FontListSerializable::APP_CONFIG_FONT_COLLECTION = "collectio
const std::string FontListSerializable::APP_CONFIG_FONT_CHAR_GAP = "char_gap"; const std::string FontListSerializable::APP_CONFIG_FONT_CHAR_GAP = "char_gap";
const std::string FontListSerializable::APP_CONFIG_FONT_LINE_GAP = "line_gap"; const std::string FontListSerializable::APP_CONFIG_FONT_LINE_GAP = "line_gap";
const std::string FontListSerializable::APP_CONFIG_ACTIVE_FONT = "activ_font";
std::string FontListSerializable::create_section_name(unsigned index) std::string FontListSerializable::create_section_name(unsigned index)
{ {
return AppConfig::SECTION_FONT + ':' + std::to_string(index); return AppConfig::SECTION_FONT + ':' + std::to_string(index);
@ -143,3 +145,59 @@ void FontListSerializable::store_font_item(AppConfig & cfg,
if (fp.line_gap.has_value()) if (fp.line_gap.has_value())
cfg.set(section_name, APP_CONFIG_FONT_LINE_GAP, std::to_string(*fp.line_gap)); cfg.set(section_name, APP_CONFIG_FONT_LINE_GAP, std::to_string(*fp.line_gap));
} }
void FontListSerializable::store_font_index(AppConfig &cfg, unsigned index) {
// store actual font index
cfg.clear_section(AppConfig::SECTION_FONT);
// activ font first index is +1 to correspond with section name
std::string activ_font = std::to_string(index);
cfg.set(AppConfig::SECTION_FONT, APP_CONFIG_ACTIVE_FONT, activ_font);
}
std::optional<size_t> FontListSerializable::load_font_index(const AppConfig &cfg)
{
if (!cfg.has_section(AppConfig::SECTION_FONT)) return {};
auto section = cfg.get_section(AppConfig::SECTION_FONT);
auto it = section.find(APP_CONFIG_ACTIVE_FONT);
if (it == section.end()) return {};
size_t active_font = static_cast<size_t>(std::atoi(it->second.c_str()));
// order in config starts with number 1
return active_font - 1;
}
FontList FontListSerializable::load_font_list(const AppConfig &cfg)
{
FontList result;
// human readable index inside of config starts from 1 !!
unsigned index = 1;
std::string section_name = create_section_name(
index);
while (cfg.has_section(section_name)) {
std::optional<FontItem> fi = load_font_item(cfg.get_section(section_name));
if (fi.has_value()) result.emplace_back(*fi);
section_name = create_section_name(++index);
}
return result;
}
void FontListSerializable::store_font_list(AppConfig &cfg, const FontList font_list)
{
// store styles
unsigned index = 1;
for (const FontItem &fi : font_list) {
// skip file paths + fonts from other OS(loaded from .3mf)
assert(fi.type == WxFontUtils::get_actual_type());
// if (fi.type != WxFontUtils::get_actual_type()) continue;
store_font_item(cfg, fi, index++);
}
// remove rest of font sections (after deletation)
std::string section_name = create_section_name(index);
while (cfg.has_section(section_name)) {
cfg.clear_section(section_name);
section_name = create_section_name(++index);
}
cfg.save();
}

View File

@ -29,14 +29,22 @@ class FontListSerializable
static const std::string APP_CONFIG_FONT_COLLECTION; static const std::string APP_CONFIG_FONT_COLLECTION;
static const std::string APP_CONFIG_FONT_CHAR_GAP; static const std::string APP_CONFIG_FONT_CHAR_GAP;
static const std::string APP_CONFIG_FONT_LINE_GAP; static const std::string APP_CONFIG_FONT_LINE_GAP;
static const std::string APP_CONFIG_ACTIVE_FONT;
public: public:
FontListSerializable() = delete; FontListSerializable() = delete;
static void store_font_index(AppConfig &cfg, unsigned index);
static std::optional<size_t> load_font_index(const AppConfig &cfg);
static FontList load_font_list(const AppConfig &cfg);
static void store_font_list(AppConfig &cfg, const FontList font_list);
private:
static std::string create_section_name(unsigned index); static std::string create_section_name(unsigned index);
static std::optional<FontItem> load_font_item(const std::map<std::string, std::string> &app_cfg_section); static std::optional<FontItem> load_font_item(const std::map<std::string, std::string> &app_cfg_section);
static void store_font_item(AppConfig &cfg, const FontItem &fi, unsigned index); static void store_font_item(AppConfig &cfg, const FontItem &fi, unsigned index);
private:
// TODO: move to app config like read from section // TODO: move to app config like read from section
static bool read(const std::map<std::string, std::string>& section, const std::string& key, bool& value); static bool read(const std::map<std::string, std::string>& section, const std::string& key, bool& value);
static bool read(const std::map<std::string, std::string>& section, const std::string& key, float& value); static bool read(const std::map<std::string, std::string>& section, const std::string& key, float& value);

View File

@ -9,62 +9,103 @@
#include "slic3r/GUI/Jobs/CreateFontStyleImagesJob.hpp" #include "slic3r/GUI/Jobs/CreateFontStyleImagesJob.hpp"
#include "slic3r/GUI/ImGuiWrapper.hpp" // check of font ranges #include "slic3r/GUI/ImGuiWrapper.hpp" // check of font ranges
#include "slic3r/Utils/FontListSerializable.hpp"
using namespace Slic3r; using namespace Slic3r;
using namespace Slic3r::GUI; using namespace Slic3r::GUI;
FontManager::FontManager(const ImWchar *language_glyph_range) FontManager::FontManager(const ImWchar *language_glyph_range)
: m_imgui_init_glyph_range(language_glyph_range) : m_imgui_init_glyph_range(language_glyph_range)
, m_font_selected(std::numeric_limits<size_t>::max())
, m_exist_style_images(false) , m_exist_style_images(false)
, m_temp_style_images(nullptr) , m_temp_style_images(nullptr)
{} {}
FontManager::~FontManager() { FontManager::~FontManager() {
free_imgui_fonts(); clear_imgui_font();
free_style_images(); free_style_images();
} }
void FontManager::init(const AppConfig *cfg, const FontList &default_font_list)
{
FontList font_list = (cfg != nullptr) ?
FontListSerializable::load_font_list(*cfg) :
default_font_list;
if (font_list.empty()) font_list = default_font_list;
for (FontItem &fi : font_list) {
make_unique_name(fi.name);
m_font_list.push_back({fi});
}
std::optional<size_t> activ_index_opt = (cfg != nullptr) ?
FontListSerializable::load_font_index(*cfg) :
std::optional<size_t>{};
size_t activ_index = activ_index_opt.has_value() ? *activ_index_opt : 0;
if (activ_index >= m_font_list.size()) activ_index = 0;
// find valid font item
if (!load_font(activ_index)) {
m_font_list.erase(m_font_list.begin() + activ_index);
activ_index = 0;
while (m_font_list.empty() || !load_font(activ_index))
m_font_list.erase(m_font_list.begin());
// no one style from config is loadable
if (m_font_list.empty()) {
// set up default font list
for (FontItem fi : default_font_list) {
make_unique_name(fi.name);
m_font_list.push_back({std::move(fi)});
}
// try to load first default font
bool loaded = load_font(activ_index);
assert(loaded);
}
}
}
bool FontManager::store_font_list_to_app_config(AppConfig *cfg)
{
assert(cfg != nullptr);
if (cfg == nullptr) return false;
if (exist_stored_style()) {
// update stored item
m_font_list[m_style_cache.font_index].font_item = m_style_cache.font_item;
} else {
// add new into stored list
FontItem &fi = m_style_cache.font_item;
make_unique_name(fi.name);
m_style_cache.font_index = m_font_list.size();
m_font_list.push_back({fi});
}
FontListSerializable::store_font_index(*cfg, m_style_cache.font_index);
FontList font_list;
font_list.reserve(m_font_list.size());
for (const Item &item : m_font_list) font_list.push_back(item.font_item);
FontListSerializable::store_font_list(*cfg, font_list);
return true;
}
void FontManager::swap(size_t i1, size_t i2) { void FontManager::swap(size_t i1, size_t i2) {
if (i1 >= m_font_list.size() || if (i1 >= m_font_list.size() ||
i2 >= m_font_list.size()) return; i2 >= m_font_list.size()) return;
std::swap(m_font_list[i1], m_font_list[i2]); std::swap(m_font_list[i1], m_font_list[i2]);
// fix selected index // fix selected index
if (!is_activ_font()) return; if (!exist_stored_style()) return;
if (m_font_selected == i1) { if (m_style_cache.font_index == i1) {
m_font_selected = i2; m_style_cache.font_index = i2;
} else if (m_font_selected == i2) { } else if (m_style_cache.font_index == i2) {
m_font_selected = i1; m_style_cache.font_index = i1;
} }
} }
void FontManager::duplicate() { duplicate(m_font_selected); }
void FontManager::duplicate(size_t index) {
if (index >= m_font_list.size()) return;
Item item = m_font_list[index]; // copy
make_unique_name(item.font_item.name);
item.truncated_name.clear();
// take original font imgui pointer
//ImFont *imgui_font = get_imgui_font(index);
//if (imgui_font != nullptr)
// m_font_list[index].imgui_font_index.reset();
m_font_list.insert(m_font_list.begin() + index, item);
// fix selected index
if (!is_activ_font()) return;
if (index < m_font_selected) ++m_font_selected;
}
void FontManager::erase(size_t index) { void FontManager::erase(size_t index) {
if (index >= m_font_list.size()) return; if (index >= m_font_list.size()) return;
//ImFont *imgui_font = get_imgui_font(index);
//if (imgui_font != nullptr)
// IM_DELETE(imgui_font);
// fix selected index // fix selected index
if (is_activ_font() && index < m_font_selected) if (exist_stored_style() &&
--m_font_selected; index < m_style_cache.font_index)
--m_style_cache.font_index;
m_font_list.erase(m_font_list.begin() + index); m_font_list.erase(m_font_list.begin() + index);
} }
@ -79,9 +120,7 @@ bool FontManager::wx_font_changed(std::unique_ptr<Emboss::FontFile> font_file)
font_file = WxFontUtils::create_font_file(*wx_font); font_file = WxFontUtils::create_font_file(*wx_font);
if (font_file == nullptr) return false; if (font_file == nullptr) return false;
} }
m_font_list[m_font_selected].font_file_with_cache = m_style_cache.font_file = Emboss::FontFileWithCache(std::move(font_file));
Emboss::FontFileWithCache(std::move(font_file));
auto &fi = get_font_item(); auto &fi = get_font_item();
fi.type = WxFontUtils::get_actual_type(); fi.type = WxFontUtils::get_actual_type();
fi.path = WxFontUtils::store_wxFont(*wx_font); fi.path = WxFontUtils::store_wxFont(*wx_font);
@ -93,38 +132,41 @@ bool FontManager::wx_font_changed(std::unique_ptr<Emboss::FontFile> font_file)
bool FontManager::load_font(size_t font_index) bool FontManager::load_font(size_t font_index)
{ {
if (font_index >= m_font_list.size()) return false; if (font_index >= m_font_list.size()) return false;
std::swap(font_index, m_font_selected); if (!load_font(m_font_list[font_index].font_item)) return false;
bool is_loaded = load_active_font(); m_style_cache.font_index = font_index;
if (!is_loaded) std::swap(font_index, m_font_selected); m_style_cache.stored_wx_font = m_style_cache.wx_font;
return is_loaded; return true;
} }
bool FontManager::load_font(size_t font_index, const wxFont &font) bool FontManager::load_font(const FontItem &fi) {
if (fi.type == FontItem::Type::file_path) {
std::unique_ptr<Emboss::FontFile> font_ptr =
Emboss::create_font_file(fi.path.c_str());
if (font_ptr == nullptr) return false;
m_style_cache.wx_font = {};
m_style_cache.font_file =
Emboss::FontFileWithCache(std::move(font_ptr));
m_style_cache.font_item = fi; // copy
m_style_cache.font_index = std::numeric_limits<size_t>::max();
m_style_cache.stored_wx_font = {};
return true;
}
if (fi.type != WxFontUtils::get_actual_type()) return false;
std::optional<wxFont> wx_font_opt = WxFontUtils::load_wxFont(fi.path);
if (!wx_font_opt.has_value()) return false;
return load_font(fi, *wx_font_opt);
}
bool FontManager::load_font(const FontItem &fi, const wxFont &font)
{ {
if (font_index >= m_font_list.size()) return false; if (!set_wx_font(font)) return false;
std::swap(font_index, m_font_selected); m_style_cache.font_item = fi; // copy
bool is_loaded = set_wx_font(font); m_style_cache.font_index = std::numeric_limits<size_t>::max();
if (!is_loaded) std::swap(font_index, m_font_selected); m_style_cache.stored_wx_font = {};
return is_loaded; return true;
} }
static std::string get_file_name(const std::string &file_path) bool FontManager::is_activ_font() { return m_style_cache.font_file.has_value(); }
{
size_t pos_last_delimiter = file_path.find_last_of("/\\");
size_t pos_point = file_path.find_last_of('.');
size_t offset = pos_last_delimiter + 1;
size_t count = pos_point - pos_last_delimiter - 1;
return file_path.substr(offset, count);
}
bool FontManager::load_active_font()
{
return set_up_font_file(m_font_selected);
}
bool FontManager::is_activ_font() {
return m_font_selected < m_font_list.size();
}
bool FontManager::load_first_valid_font() { bool FontManager::load_first_valid_font() {
while (!m_font_list.empty()) { while (!m_font_list.empty()) {
@ -135,127 +177,47 @@ bool FontManager::load_first_valid_font() {
return false; return false;
} }
void FontManager::add_font(FontItem font_item) const FontItem* FontManager::get_stored_font_item() const
{ {
make_unique_name(font_item.name); if (m_style_cache.font_index >= m_font_list.size()) return nullptr;
Item item; return &m_font_list[m_style_cache.font_index].font_item;
item.font_item = font_item;
m_font_list.push_back(item);
} }
void FontManager::add_fonts(FontList font_list) const std::optional<wxFont> &FontManager::get_stored_wx_font() const { return m_style_cache.stored_wx_font; }
{
for (const FontItem &fi : font_list)
add_font(fi);
}
std::shared_ptr<const Emboss::FontFile> &FontManager::get_font_file() const FontItem &FontManager::get_font_item() const { return m_style_cache.font_item; }
{ FontItem &FontManager::get_font_item() { return m_style_cache.font_item; }
// TODO: fix not selected font const FontProp &FontManager::get_font_prop() const { return get_font_item().prop; }
//if (!is_activ_font()) return nullptr; FontProp &FontManager::get_font_prop() { return get_font_item().prop; }
return m_font_list[m_font_selected].font_file_with_cache.font_file; const std::optional<wxFont> &FontManager::get_wx_font() const { return m_style_cache.wx_font; }
} std::optional<wxFont> &FontManager::get_wx_font() { return m_style_cache.wx_font; }
const FontItem &FontManager::get_font_item() const bool FontManager::exist_stored_style() const { return m_style_cache.font_index != std::numeric_limits<size_t>::max(); }
{ size_t FontManager::get_style_index() const { return m_style_cache.font_index; }
// TODO: fix not selected font Emboss::FontFileWithCache &FontManager::get_font_file_with_cache() { return m_style_cache.font_file; }
//if (!is_activ_font()) return nullptr; std::string &FontManager::get_truncated_name() { return m_style_cache.truncated_name; }
return m_font_list[m_font_selected].font_item;
}
FontItem &FontManager::get_font_item()
{
// TODO: fix not selected font
//if (!is_activ_font()) return nullptr;
return m_font_list[m_font_selected].font_item;
}
const FontProp &FontManager::get_font_prop() const
{
// TODO: fix not selected font
//if (!is_activ_font()) return nullptr;
return m_font_list[m_font_selected].font_item.prop;
}
FontProp &FontManager::get_font_prop()
{
// TODO: fix not selected font
return m_font_list[m_font_selected].font_item.prop;
}
std::optional<wxFont> &FontManager::get_wx_font()
{
//if (!is_activ_font()) return {};
return m_font_list[m_font_selected].wx_font;
//std::optional<wxFont> &wx_font = m_font_list[m_font_selected].wx_font;
//if (wx_font.has_value()) return wx_font;
//const FontItem &fi = get_font_item();
//if (fi.type != WxFontUtils::get_actual_type()) return {};
//wx_font = WxFontUtils::load_wxFont(fi.path);
//return wx_font;
}
bool FontManager::set_wx_font(const wxFont &wx_font) {
return set_wx_font(m_font_selected, wx_font);
}
std::string &FontManager::get_truncated_name()
{
return m_font_list[m_font_selected].truncated_name;
}
const std::optional<wxFont> &FontManager::get_wx_font() const
{
return m_font_list[m_font_selected].wx_font;
}
void FontManager::clear_glyphs_cache() void FontManager::clear_glyphs_cache()
{ {
if (!is_activ_font()) return; Emboss::FontFileWithCache &ff = m_style_cache.font_file;
Emboss::FontFileWithCache &ff = m_font_list[m_font_selected].font_file_with_cache;
if (!ff.has_value()) return; if (!ff.has_value()) return;
ff.cache = std::make_shared<Emboss::Glyphs>(); ff.cache = std::make_shared<Emboss::Glyphs>();
} }
void FontManager::clear_imgui_font() { void FontManager::clear_imgui_font() { m_style_cache.atlas.Clear(); }
// TODO: improove to clear only actual font
if (!is_activ_font()) return;
free_imgui_fonts();
return;
ImFont *imgui_font = get_imgui_font(m_font_selected);
m_font_list[m_font_selected].imgui_font_index.reset();
if (imgui_font != nullptr) IM_DELETE(imgui_font);
}
ImFont *FontManager::get_imgui_font() ImFont *FontManager::get_imgui_font()
{
return get_imgui_font(m_font_selected);
}
ImFont *FontManager::create_imgui_font(const std::string &text)
{
return create_imgui_font(m_font_selected, text);
}
ImFont *FontManager::get_imgui_font(size_t item_index)
{ {
if (!is_activ_font()) return nullptr; if (!is_activ_font()) return nullptr;
Item &item = m_font_list[item_index];
// check is already loaded
if (!item.imgui_font_index.has_value()) return nullptr;
size_t index = *item.imgui_font_index; ImVector<ImFont *> &fonts = m_style_cache.atlas.Fonts;
ImVector<ImFont *> &fonts = m_imgui_font_atlas.Fonts; if (fonts.empty()) return nullptr;
// check correct index // check correct index
int f_size = fonts.size(); int f_size = fonts.size();
assert(f_size > 0 && index < (size_t) f_size); assert(f_size == 1);
if (f_size <= 0 || index >= (size_t) f_size) return nullptr; if (f_size != 1) return nullptr;
ImFont *font = fonts[index]; ImFont *font = fonts.front();
if (font == nullptr) return nullptr; if (font == nullptr) return nullptr;
if (!font->IsLoaded()) return nullptr; if (!font->IsLoaded()) return nullptr;
if (font->Scale <= 0.f) return nullptr; if (font->Scale <= 0.f) return nullptr;
@ -264,25 +226,13 @@ ImFont *FontManager::get_imgui_font(size_t item_index)
return font; return font;
} }
void FontManager::free_except_active_font() { const std::vector<FontManager::Item> &FontManager::get_styles() const{ return m_font_list; }
free_imgui_fonts();
// free font_files ImFont* FontManager::extend_imgui_font_range(size_t index, const std::string& text)
const Item &act_item = m_font_list[m_font_selected];
for (auto &item : m_font_list) {
if (&item == &act_item) continue; // keep alive actual font file
item.font_file_with_cache = {};
}
}
const std::vector<FontManager::Item> &FontManager::get_styles() const
{ {
return m_font_list; // TODO: start using merge mode
} // ImFontConfig::MergeMode = true;
return create_imgui_font(text);
const FontManager::Item &FontManager::get_activ_style() const
{
return m_font_list[m_font_selected];
} }
void FontManager::make_unique_name(std::string &name) void FontManager::make_unique_name(std::string &name)
@ -310,46 +260,10 @@ void FontManager::make_unique_name(std::string &name)
name = new_name; name = new_name;
} }
bool FontManager::set_up_font_file(size_t item_index)
{
Item &item = m_font_list[item_index];
FontItem &fi = item.font_item;
if (fi.type == FontItem::Type::file_path) {
// fill font name after load from .3mf
if (fi.name.empty()) fi.name = get_file_name(fi.path);
std::unique_ptr<Emboss::FontFile> font_ptr =
Emboss::create_font_file(fi.path.c_str());
if (font_ptr == nullptr) return false;
item.font_file_with_cache =
Emboss::FontFileWithCache(std::move(font_ptr));
return true;
}
if (fi.type != WxFontUtils::get_actual_type()) return false;
if (!item.wx_font.has_value())
item.wx_font = WxFontUtils::load_wxFont(fi.path);
if (!item.wx_font.has_value()) return false;
return set_wx_font(item_index, *item.wx_font);
}
ImFont* FontManager::extend_imgui_font_range(size_t index, const std::string& text)
{
auto &font_index_opt = m_font_list[m_font_selected].imgui_font_index;
if (!font_index_opt.has_value())
return create_imgui_font(index, text);
// TODO: start using merge mode
// ImFontConfig::MergeMode = true;
free_imgui_fonts();
return create_imgui_font(index, text);
}
void FontManager::init_trunc_names(float max_width) { void FontManager::init_trunc_names(float max_width) {
for (auto &s : m_font_list) { for (auto &s : m_font_list)
if (s.truncated_name.empty()) if (s.truncated_name.empty())
s.truncated_name = ImGuiWrapper::trunc(s.font_item.name, max_width); s.truncated_name = ImGuiWrapper::trunc(s.font_item.name, max_width);
}
} }
#include "slic3r/GUI/Jobs/CreateFontStyleImagesJob.hpp" #include "slic3r/GUI/Jobs/CreateFontStyleImagesJob.hpp"
@ -396,17 +310,19 @@ void FontManager::init_style_images(const Vec2i &max_size,
m_temp_style_images = std::make_shared<StyleImagesData::StyleImages>(); m_temp_style_images = std::make_shared<StyleImagesData::StyleImages>();
StyleImagesData::Items styles; StyleImagesData::Items styles;
styles.reserve(m_font_list.size()); styles.reserve(m_font_list.size());
for (Item &item : m_font_list) { for (const Item &item : m_font_list) {
size_t index = &item - &m_font_list.front(); const FontItem &fi = item.font_item;
if (!item.font_file_with_cache.has_value() && !set_up_font_file(index)) std::optional<wxFont> wx_font_opt = WxFontUtils::load_wxFont(fi.path);
continue; if (!wx_font_opt.has_value()) continue;
std::unique_ptr<Emboss::FontFile> font_file =
WxFontUtils::create_font_file(*wx_font_opt);
if (font_file == nullptr) continue;
styles.push_back({ styles.push_back({
item.font_file_with_cache, Emboss::FontFileWithCache(std::move(font_file)),
item.font_item.name, fi.name,
item.font_item.prop fi.prop
}); });
} }
auto &worker = wxGetApp().plater()->get_ui_job_worker(); auto &worker = wxGetApp().plater()->get_ui_job_worker();
StyleImagesData data{std::move(styles), max_size, text, m_temp_style_images}; StyleImagesData data{std::move(styles), max_size, text, m_temp_style_images};
queue_job(worker, std::make_unique<CreateFontStyleImagesJob>(std::move(data))); queue_job(worker, std::make_unique<CreateFontStyleImagesJob>(std::move(data)));
@ -428,13 +344,6 @@ void FontManager::free_style_images() {
m_exist_style_images = false; m_exist_style_images = false;
} }
void FontManager::free_imgui_fonts()
{
for (auto &item : m_font_list)
item.imgui_font_index.reset();
m_imgui_font_atlas.Clear();
}
float FontManager::min_imgui_font_size = 18.f; float FontManager::min_imgui_font_size = 18.f;
float FontManager::max_imgui_font_size = 60.f; float FontManager::max_imgui_font_size = 60.f;
float FontManager::get_imgui_font_size(const FontProp &prop, float FontManager::get_imgui_font_size(const FontProp &prop,
@ -452,28 +361,26 @@ float FontManager::get_imgui_font_size(const FontProp &prop,
return c1 * std::abs(prop.size_in_mm) / 0.3528f; return c1 * std::abs(prop.size_in_mm) / 0.3528f;
} }
ImFont *FontManager::create_imgui_font(size_t index, const std::string &text) ImFont *FontManager::create_imgui_font(const std::string &text)
{ {
free_imgui_fonts(); // TODO: remove it after correct initialization auto& ff = m_style_cache.font_file;
if (!ff.has_value()) return nullptr;
if (index >= m_font_list.size()) return nullptr; const Emboss::FontFile &font_file = *ff.font_file;
Item &item = m_font_list[index];
if (!item.font_file_with_cache.has_value()) return nullptr;
const Emboss::FontFile &font_file = *item.font_file_with_cache.font_file;
// TODO: Create glyph range // TODO: Create glyph range
ImFontGlyphRangesBuilder builder; ImFontGlyphRangesBuilder builder;
builder.AddRanges(m_imgui_init_glyph_range); builder.AddRanges(m_imgui_init_glyph_range);
if (!text.empty()) if (!text.empty())
builder.AddText(text.c_str()); builder.AddText(text.c_str());
item.font_ranges.clear();
builder.BuildRanges(&item.font_ranges); ImVector<ImWchar> &ranges = m_style_cache.ranges;
ranges.clear();
builder.BuildRanges(&ranges);
m_imgui_font_atlas.Flags |= ImFontAtlasFlags_NoMouseCursors | m_style_cache.atlas.Flags |= ImFontAtlasFlags_NoMouseCursors |
ImFontAtlasFlags_NoPowerOfTwoHeight; ImFontAtlasFlags_NoPowerOfTwoHeight;
const FontProp &font_prop = item.font_item.prop; const FontProp &font_prop = m_style_cache.font_item.prop;
float font_size = get_imgui_font_size(font_prop, font_file); float font_size = get_imgui_font_size(font_prop, font_file);
if (font_size < min_imgui_font_size) if (font_size < min_imgui_font_size)
font_size = min_imgui_font_size; font_size = min_imgui_font_size;
@ -499,12 +406,12 @@ ImFont *FontManager::create_imgui_font(size_t index, const std::string &text)
font_config.FontDataOwnedByAtlas = false; font_config.FontDataOwnedByAtlas = false;
const std::vector<unsigned char> &buffer = *font_file.data; const std::vector<unsigned char> &buffer = *font_file.data;
ImFont * font = m_imgui_font_atlas.AddFontFromMemoryTTF( ImFont * font = m_style_cache.atlas.AddFontFromMemoryTTF(
(void *) buffer.data(), buffer.size(), font_size, &font_config, item.font_ranges.Data); (void *) buffer.data(), buffer.size(), font_size, &font_config, m_style_cache.ranges.Data);
unsigned char *pixels; unsigned char *pixels;
int width, height; int width, height;
m_imgui_font_atlas.GetTexDataAsAlpha8(&pixels, &width, &height); m_style_cache.atlas.GetTexDataAsAlpha8(&pixels, &width, &height);
// Upload texture to graphics system // Upload texture to graphics system
GLint last_texture; GLint last_texture;
@ -523,32 +430,23 @@ ImFont *FontManager::create_imgui_font(size_t index, const std::string &text)
GL_ALPHA, GL_UNSIGNED_BYTE, pixels)); GL_ALPHA, GL_UNSIGNED_BYTE, pixels));
// Store our identifier // Store our identifier
m_imgui_font_atlas.TexID = (ImTextureID) (intptr_t) font_texture; m_style_cache.atlas.TexID = (ImTextureID) (intptr_t) font_texture;
assert(!m_imgui_font_atlas.Fonts.empty()); assert(!m_style_cache.atlas.Fonts.empty());
if (m_imgui_font_atlas.Fonts.empty()) return nullptr; if (m_style_cache.atlas.Fonts.empty()) return nullptr;
assert(font == m_imgui_font_atlas.Fonts.back()); assert(font == m_style_cache.atlas.Fonts.back());
item.imgui_font_index = m_imgui_font_atlas.Fonts.size() - 1;
assert(font->IsLoaded()); assert(font->IsLoaded());
return font; return font;
} }
bool FontManager::set_wx_font(size_t item_index, const wxFont &wx_font) { bool FontManager::set_wx_font(const wxFont &wx_font) {
std::unique_ptr<Emboss::FontFile> font_file = std::unique_ptr<Emboss::FontFile> font_file =
WxFontUtils::create_font_file(wx_font); WxFontUtils::create_font_file(wx_font);
if (font_file == nullptr) return false; if (font_file == nullptr) return false;
m_style_cache.font_file =
Item &item = m_font_list[item_index];
item.font_file_with_cache =
Emboss::FontFileWithCache(std::move(font_file)); Emboss::FontFileWithCache(std::move(font_file));
item.wx_font = wx_font; m_style_cache.wx_font = wx_font; // copy
FontItem &fi = m_style_cache.font_item;
FontItem &fi = item.font_item;
fi.type = WxFontUtils::get_actual_type(); fi.type = WxFontUtils::get_actual_type();
// fill font name after load from .3mf
if (fi.name.empty())
fi.name = WxFontUtils::get_human_readable_name(*item.wx_font);
clear_imgui_font(); clear_imgui_font();
return true; return true;
} }

View File

@ -1,10 +1,13 @@
#ifndef slic3r_FontManager_hpp_ #ifndef slic3r_FontManager_hpp_
#define slic3r_FontManager_hpp_ #define slic3r_FontManager_hpp_
#include <memory>
#include <optional> #include <optional>
#include <string>
#include <imgui/imgui.h> #include <imgui/imgui.h>
#include <GL/glew.h> #include <GL/glew.h>
#include <libslic3r/Emboss.hpp> #include <libslic3r/Emboss.hpp>
#include <libslic3r/AppConfig.hpp>
class wxFont; class wxFont;
@ -23,6 +26,21 @@ public:
FontManager(const ImWchar *language_glyph_range); FontManager(const ImWchar *language_glyph_range);
~FontManager(); ~FontManager();
/// <summary>
/// Load font style list from config
/// Also select actual activ font
/// </summary>
/// <param name="cfg">Application configuration loaded from file "PrusaSlicer.ini"</param>
/// <param name="default_font_list">Used when list is not loadable from config</param>
void init(const AppConfig *cfg, const FontList &default_font_list);
/// <summary>
/// Write font list into AppConfig
/// </summary>
/// <param name="cfg">Stor into this configuration</param>
/// <param name="item_to_store">Configuration</param>
bool store_font_list_to_app_config(AppConfig *cfg);
/// <summary> /// <summary>
/// Change order of style item in m_font_list. /// Change order of style item in m_font_list.
/// Fix selected font index when (i1 || i2) == m_font_selected /// Fix selected font index when (i1 || i2) == m_font_selected
@ -31,11 +49,6 @@ public:
/// <param name="i2">Second index to m_font_list</param> /// <param name="i2">Second index to m_font_list</param>
void swap(size_t i1, size_t i2); void swap(size_t i1, size_t i2);
/// <summary>
/// Duplicate selected font style
/// </summary>
void duplicate();
/// <summary> /// <summary>
/// Remove style from m_font_list. /// Remove style from m_font_list.
/// Fix selected font index when index is under m_font_selected /// Fix selected font index when index is under m_font_selected
@ -57,8 +70,10 @@ public:
/// <param name="font_index">New font index(from m_font_list range)</param> /// <param name="font_index">New font index(from m_font_list range)</param>
/// <returns>True on succes. False on fail load font</returns> /// <returns>True on succes. False on fail load font</returns>
bool load_font(size_t font_index); bool load_font(size_t font_index);
// load font style not stored in list
bool load_font(const FontItem &fi);
// fastering load font on index by wxFont, ignore type and descriptor // fastering load font on index by wxFont, ignore type and descriptor
bool load_font(size_t font_index, const wxFont &font); bool load_font(const FontItem &fi, const wxFont &font);
// clear actual selected glyphs cache // clear actual selected glyphs cache
void clear_glyphs_cache(); void clear_glyphs_cache();
@ -70,13 +85,11 @@ public:
// used at initialize phaze - fonts could be modified in appConfig file by user // used at initialize phaze - fonts could be modified in appConfig file by user
bool load_first_valid_font(); bool load_first_valid_font();
// add font into manager // getter on stored fontItem
void add_font(FontItem font_item); const FontItem *get_stored_font_item() const;
// add multiple font into manager
void add_fonts(FontList font_list);
// getter on active font file for access to glyphs // getter on stored wxFont
std::shared_ptr<const Emboss::FontFile> &get_font_file(); const std::optional<wxFont> &get_stored_wx_font() const;
// getter on active font item for access to font property // getter on active font item for access to font property
const FontItem &get_font_item() const; const FontItem &get_font_item() const;
@ -90,12 +103,19 @@ public:
const std::optional<wxFont> &get_wx_font() const; const std::optional<wxFont> &get_wx_font() const;
std::optional<wxFont> &get_wx_font(); std::optional<wxFont> &get_wx_font();
// setter of font for actual selection bool exist_stored_style() const;
bool set_wx_font(const wxFont &wx_font); size_t get_style_index() const;
// getter on font file with cache
Emboss::FontFileWithCache &get_font_file_with_cache();
// Getter for cached trucated name for style list selector // Getter for cached trucated name for style list selector
std::string &get_truncated_name(); std::string &get_truncated_name();
// setter of font for actual selection
bool set_wx_font(const wxFont &wx_font);
// Getter on acitve font pointer for imgui // Getter on acitve font pointer for imgui
// Initialize imgui font(generate texture) when doesn't exist yet. // Initialize imgui font(generate texture) when doesn't exist yet.
// Extend font atlas when not in glyph range // Extend font atlas when not in glyph range
@ -103,9 +123,6 @@ public:
// initialize font range by unique symbols in text // initialize font range by unique symbols in text
ImFont *create_imgui_font(const std::string& text); ImFont *create_imgui_font(const std::string& text);
// free used memory and font file data
void free_except_active_font();
// init truncated names of styles // init truncated names of styles
void init_trunc_names(float max_width); void init_trunc_names(float max_width);
@ -120,7 +137,6 @@ public:
struct Item; struct Item;
// access to all managed font styles // access to all managed font styles
const std::vector<Item> &get_styles() const; const std::vector<Item> &get_styles() const;
const Item &get_activ_style() const; // TODO: rename to style
/// <summary> /// <summary>
/// Describe image in GPU to show settings of style /// Describe image in GPU to show settings of style
@ -140,22 +156,12 @@ public:
/// </summary> /// </summary>
struct Item struct Item
{ {
// define font, style and other property of text
FontItem font_item; FontItem font_item;
// cache for view font name with maximal width in imgui // cache for view font name with maximal width in imgui
std::string truncated_name; std::string truncated_name;
// share font file data with emboss job thread
Emboss::FontFileWithCache font_file_with_cache;
std::optional<size_t> imgui_font_index;
// must live same as imgui_font inside of atlas
ImVector<ImWchar> font_ranges;
// wx widget font
std::optional<wxFont> wx_font;
// visualization of style // visualization of style
std::optional<StyleImage> image; std::optional<StyleImage> image;
}; };
@ -168,35 +174,51 @@ public:
static float min_imgui_font_size; static float min_imgui_font_size;
static float max_imgui_font_size; static float max_imgui_font_size;
static float get_imgui_font_size(const FontProp& prop, const Emboss::FontFile& file); static float get_imgui_font_size(const FontProp& prop, const Emboss::FontFile& file);
private: private:
ImFontAtlas m_imgui_font_atlas; /// <summary>
/// Cache data from style to reduce amount of:
/// 1) loading font from file
/// 2) Create atlas of symbols for imgui
/// 3) Keep loaded(and modified by style) glyphs from font
/// </summary>
struct StyleCache
{
// share font file data with emboss job thread
Emboss::FontFileWithCache font_file = {};
void duplicate(size_t index); // must live same as imgui_font inside of atlas
// load actual selected font ImVector<ImWchar> ranges = {};
ImFont *create_imgui_font(size_t index, const std::string &text);
bool load_active_font(); // Keep only actual style in atlas
ImFontAtlas atlas = {};
bool set_wx_font(size_t item_index, const wxFont &wx_font); // wx widget font
std::optional<wxFont> wx_font = {};
// getter on index selected font pointer for imgui // cache for view font name with maximal width in imgui
// text could extend font atlas when not in glyph range std::string truncated_name;
ImFont *get_imgui_font(size_t item_index);
// actual used font item
FontItem font_item = {};
// cache for stored wx font to not create every frame
std::optional<wxFont> stored_wx_font;
// index into m_font_list
size_t font_index = std::numeric_limits<size_t>::max();
} m_style_cache;
// extend actual imgui font when exist unknown char in text // extend actual imgui font when exist unknown char in text
// NOTE: imgui_font has to be unused // NOTE: imgui_font has to be unused
// return true when extend range otherwise FALSE // return true when extend range otherwise FALSE
ImFont *extend_imgui_font_range(size_t font_index, const std::string &text); ImFont *extend_imgui_font_range(size_t font_index, const std::string &text);
void free_imgui_fonts();
bool set_up_font_file(size_t item_index);
void make_unique_name(std::string &name); void make_unique_name(std::string &name);
// Privat member // Privat member
std::vector<Item> m_font_list; std::vector<Item> m_font_list;
size_t m_font_selected; // index to m_font_list
/// <summary> /// <summary>
/// Keep data needed to create Font Style Images in Job /// Keep data needed to create Font Style Images in Job