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 {
class MeshRaycaster;
struct EmbossDataBase;
class GLGizmoEmboss : public GLGizmoBase
{
@ -121,18 +122,18 @@ private:
/// TODO: make more general, static and move to ImGuiWrapper
/// </summary>
/// <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,
ImGuiInputTextFlags flags = 0);
bool rev_checkbox(const std::string &name, bool &value, 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_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, const std::optional<int> *default_value,
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);
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);
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);
const ImVec2 &get_minimal_window_size() const;
@ -145,8 +146,8 @@ private:
bool choose_true_type_file();
bool choose_svg_file();
// Create object described how to make a Volume
TextConfiguration create_configuration();
// prepare base data for emboss text
EmbossDataBase create_emboss_data_base();
bool load_configuration(ModelVolume *volume);
// Create notification when unknown font type is used
@ -154,8 +155,6 @@ private:
void create_notification_not_valid_font(const TextConfiguration& tc);
void remove_notification_not_valid_font();
std::string create_volume_name();
// This configs holds GUI layout size given by translated texts.
// etc. When language changes, GUI is recreated and this class constructed again,
// so the change takes effect. (info by GLGizmoFdmSupports.hpp)
@ -212,7 +211,7 @@ private:
std::optional<ImVec2> m_set_window_offset;
bool m_is_advanced_edit_style = false;
FontManager m_font_manager;
FontManager m_style_manager;
// Keep sorted list of loadable face names
struct Facenames
@ -227,15 +226,12 @@ private:
std::vector<bool> exist_textures = {};
} 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
std::string m_text;
// actual volume
ModelVolume *m_volume;
// True when m_text contain character unknown by selected font
bool m_text_contain_unknown_glyph = false;
@ -245,9 +241,6 @@ private:
// cancel for rendering font name
bool m_allow_update_rendered_font;
// actual volume
ModelVolume *m_volume;
// Rotation 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_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
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_LINE_GAP = "line_gap";
const std::string FontListSerializable::APP_CONFIG_ACTIVE_FONT = "activ_font";
std::string FontListSerializable::create_section_name(unsigned index)
{
return AppConfig::SECTION_FONT + ':' + std::to_string(index);
@ -142,4 +144,60 @@ void FontListSerializable::store_font_item(AppConfig & cfg,
cfg.set(section_name, APP_CONFIG_FONT_CHAR_GAP, std::to_string(*fp.char_gap));
if (fp.line_gap.has_value())
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_CHAR_GAP;
static const std::string APP_CONFIG_FONT_LINE_GAP;
static const std::string APP_CONFIG_ACTIVE_FONT;
public:
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::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);
private:
// 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, float& value);

View File

@ -9,62 +9,103 @@
#include "slic3r/GUI/Jobs/CreateFontStyleImagesJob.hpp"
#include "slic3r/GUI/ImGuiWrapper.hpp" // check of font ranges
#include "slic3r/Utils/FontListSerializable.hpp"
using namespace Slic3r;
using namespace Slic3r::GUI;
FontManager::FontManager(const ImWchar *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_temp_style_images(nullptr)
{}
FontManager::~FontManager() {
free_imgui_fonts();
clear_imgui_font();
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) {
if (i1 >= m_font_list.size() ||
i2 >= m_font_list.size()) return;
std::swap(m_font_list[i1], m_font_list[i2]);
// fix selected index
if (!is_activ_font()) return;
if (m_font_selected == i1) {
m_font_selected = i2;
} else if (m_font_selected == i2) {
m_font_selected = i1;
if (!exist_stored_style()) return;
if (m_style_cache.font_index == i1) {
m_style_cache.font_index = i2;
} else if (m_style_cache.font_index == i2) {
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) {
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
if (is_activ_font() && index < m_font_selected)
--m_font_selected;
if (exist_stored_style() &&
index < m_style_cache.font_index)
--m_style_cache.font_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);
if (font_file == nullptr) return false;
}
m_font_list[m_font_selected].font_file_with_cache =
Emboss::FontFileWithCache(std::move(font_file));
m_style_cache.font_file = Emboss::FontFileWithCache(std::move(font_file));
auto &fi = get_font_item();
fi.type = WxFontUtils::get_actual_type();
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)
{
if (font_index >= m_font_list.size()) return false;
std::swap(font_index, m_font_selected);
bool is_loaded = load_active_font();
if (!is_loaded) std::swap(font_index, m_font_selected);
return is_loaded;
if (!load_font(m_font_list[font_index].font_item)) return false;
m_style_cache.font_index = font_index;
m_style_cache.stored_wx_font = m_style_cache.wx_font;
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;
std::swap(font_index, m_font_selected);
bool is_loaded = set_wx_font(font);
if (!is_loaded) std::swap(font_index, m_font_selected);
return is_loaded;
if (!set_wx_font(font)) return false;
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;
}
static std::string get_file_name(const std::string &file_path)
{
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::is_activ_font() { return m_style_cache.font_file.has_value(); }
bool FontManager::load_first_valid_font() {
while (!m_font_list.empty()) {
@ -135,127 +177,47 @@ bool FontManager::load_first_valid_font() {
return false;
}
void FontManager::add_font(FontItem font_item)
{
make_unique_name(font_item.name);
Item item;
item.font_item = font_item;
m_font_list.push_back(item);
}
void FontManager::add_fonts(FontList font_list)
const FontItem* FontManager::get_stored_font_item() const
{
for (const FontItem &fi : font_list)
add_font(fi);
if (m_style_cache.font_index >= m_font_list.size()) return nullptr;
return &m_font_list[m_style_cache.font_index].font_item;
}
std::shared_ptr<const Emboss::FontFile> &FontManager::get_font_file()
{
// TODO: fix not selected font
//if (!is_activ_font()) return nullptr;
return m_font_list[m_font_selected].font_file_with_cache.font_file;
}
const std::optional<wxFont> &FontManager::get_stored_wx_font() const { return m_style_cache.stored_wx_font; }
const FontItem &FontManager::get_font_item() const
{
// TODO: fix not selected font
//if (!is_activ_font()) return nullptr;
return m_font_list[m_font_selected].font_item;
}
const FontItem &FontManager::get_font_item() const { return m_style_cache.font_item; }
FontItem &FontManager::get_font_item() { return m_style_cache.font_item; }
const FontProp &FontManager::get_font_prop() const { return get_font_item().prop; }
FontProp &FontManager::get_font_prop() { return get_font_item().prop; }
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; }
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;
}
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; }
Emboss::FontFileWithCache &FontManager::get_font_file_with_cache() { return m_style_cache.font_file; }
std::string &FontManager::get_truncated_name() { return m_style_cache.truncated_name; }
void FontManager::clear_glyphs_cache()
{
if (!is_activ_font()) return;
Emboss::FontFileWithCache &ff = m_font_list[m_font_selected].font_file_with_cache;
Emboss::FontFileWithCache &ff = m_style_cache.font_file;
if (!ff.has_value()) return;
ff.cache = std::make_shared<Emboss::Glyphs>();
}
void FontManager::clear_imgui_font() {
// 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);
}
void FontManager::clear_imgui_font() { m_style_cache.atlas.Clear(); }
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;
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_imgui_font_atlas.Fonts;
ImVector<ImFont *> &fonts = m_style_cache.atlas.Fonts;
if (fonts.empty()) return nullptr;
// check correct index
int f_size = fonts.size();
assert(f_size > 0 && index < (size_t) f_size);
if (f_size <= 0 || index >= (size_t) f_size) return nullptr;
ImFont *font = fonts[index];
assert(f_size == 1);
if (f_size != 1) return nullptr;
ImFont *font = fonts.front();
if (font == nullptr) return nullptr;
if (!font->IsLoaded()) return nullptr;
if (font->Scale <= 0.f) return nullptr;
@ -264,25 +226,13 @@ ImFont *FontManager::get_imgui_font(size_t item_index)
return font;
}
void FontManager::free_except_active_font() {
free_imgui_fonts();
const std::vector<FontManager::Item> &FontManager::get_styles() const{ return m_font_list; }
// free font_files
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
ImFont* FontManager::extend_imgui_font_range(size_t index, const std::string& text)
{
return m_font_list;
}
const FontManager::Item &FontManager::get_activ_style() const
{
return m_font_list[m_font_selected];
// TODO: start using merge mode
// ImFontConfig::MergeMode = true;
return create_imgui_font(text);
}
void FontManager::make_unique_name(std::string &name)
@ -310,46 +260,10 @@ void FontManager::make_unique_name(std::string &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) {
for (auto &s : m_font_list) {
for (auto &s : m_font_list)
if (s.truncated_name.empty())
s.truncated_name = ImGuiWrapper::trunc(s.font_item.name, max_width);
}
}
#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>();
StyleImagesData::Items styles;
styles.reserve(m_font_list.size());
for (Item &item : m_font_list) {
size_t index = &item - &m_font_list.front();
if (!item.font_file_with_cache.has_value() && !set_up_font_file(index))
continue;
for (const Item &item : m_font_list) {
const FontItem &fi = item.font_item;
std::optional<wxFont> wx_font_opt = WxFontUtils::load_wxFont(fi.path);
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({
item.font_file_with_cache,
item.font_item.name,
item.font_item.prop
Emboss::FontFileWithCache(std::move(font_file)),
fi.name,
fi.prop
});
}
auto &worker = wxGetApp().plater()->get_ui_job_worker();
StyleImagesData data{std::move(styles), max_size, text, m_temp_style_images};
queue_job(worker, std::make_unique<CreateFontStyleImagesJob>(std::move(data)));
@ -428,13 +344,6 @@ void FontManager::free_style_images() {
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::max_imgui_font_size = 60.f;
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;
}
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
if (index >= m_font_list.size()) return nullptr;
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;
auto& ff = m_style_cache.font_file;
if (!ff.has_value()) return nullptr;
const Emboss::FontFile &font_file = *ff.font_file;
// TODO: Create glyph range
ImFontGlyphRangesBuilder builder;
builder.AddRanges(m_imgui_init_glyph_range);
if (!text.empty())
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;
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);
if (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;
const std::vector<unsigned char> &buffer = *font_file.data;
ImFont * font = m_imgui_font_atlas.AddFontFromMemoryTTF(
(void *) buffer.data(), buffer.size(), font_size, &font_config, item.font_ranges.Data);
ImFont * font = m_style_cache.atlas.AddFontFromMemoryTTF(
(void *) buffer.data(), buffer.size(), font_size, &font_config, m_style_cache.ranges.Data);
unsigned char *pixels;
int width, height;
m_imgui_font_atlas.GetTexDataAsAlpha8(&pixels, &width, &height);
m_style_cache.atlas.GetTexDataAsAlpha8(&pixels, &width, &height);
// Upload texture to graphics system
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));
// Store our identifier
m_imgui_font_atlas.TexID = (ImTextureID) (intptr_t) font_texture;
assert(!m_imgui_font_atlas.Fonts.empty());
if (m_imgui_font_atlas.Fonts.empty()) return nullptr;
assert(font == m_imgui_font_atlas.Fonts.back());
item.imgui_font_index = m_imgui_font_atlas.Fonts.size() - 1;
m_style_cache.atlas.TexID = (ImTextureID) (intptr_t) font_texture;
assert(!m_style_cache.atlas.Fonts.empty());
if (m_style_cache.atlas.Fonts.empty()) return nullptr;
assert(font == m_style_cache.atlas.Fonts.back());
assert(font->IsLoaded());
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 =
WxFontUtils::create_font_file(wx_font);
if (font_file == nullptr) return false;
Item &item = m_font_list[item_index];
item.font_file_with_cache =
m_style_cache.font_file =
Emboss::FontFileWithCache(std::move(font_file));
item.wx_font = wx_font;
FontItem &fi = item.font_item;
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);
m_style_cache.wx_font = wx_font; // copy
FontItem &fi = m_style_cache.font_item;
fi.type = WxFontUtils::get_actual_type();
clear_imgui_font();
return true;
}

View File

@ -1,10 +1,13 @@
#ifndef slic3r_FontManager_hpp_
#define slic3r_FontManager_hpp_
#include <memory>
#include <optional>
#include <string>
#include <imgui/imgui.h>
#include <GL/glew.h>
#include <libslic3r/Emboss.hpp>
#include <libslic3r/AppConfig.hpp>
class wxFont;
@ -23,6 +26,21 @@ public:
FontManager(const ImWchar *language_glyph_range);
~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>
/// Change order of style item in m_font_list.
/// 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>
void swap(size_t i1, size_t i2);
/// <summary>
/// Duplicate selected font style
/// </summary>
void duplicate();
/// <summary>
/// Remove style from m_font_list.
/// 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>
/// <returns>True on succes. False on fail load font</returns>
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
bool load_font(size_t font_index, const wxFont &font);
bool load_font(const FontItem &fi, const wxFont &font);
// clear actual selected glyphs cache
void clear_glyphs_cache();
@ -70,13 +85,11 @@ public:
// used at initialize phaze - fonts could be modified in appConfig file by user
bool load_first_valid_font();
// add font into manager
void add_font(FontItem font_item);
// add multiple font into manager
void add_fonts(FontList font_list);
// getter on stored fontItem
const FontItem *get_stored_font_item() const;
// getter on active font file for access to glyphs
std::shared_ptr<const Emboss::FontFile> &get_font_file();
// getter on stored wxFont
const std::optional<wxFont> &get_stored_wx_font() const;
// getter on active font item for access to font property
const FontItem &get_font_item() const;
@ -90,11 +103,18 @@ public:
const std::optional<wxFont> &get_wx_font() const;
std::optional<wxFont> &get_wx_font();
// setter of font for actual selection
bool set_wx_font(const wxFont &wx_font);
bool exist_stored_style() const;
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
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
// Initialize imgui font(generate texture) when doesn't exist yet.
@ -102,9 +122,6 @@ public:
ImFont *get_imgui_font();
// initialize font range by unique symbols in 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
void init_trunc_names(float max_width);
@ -120,7 +137,6 @@ public:
struct Item;
// access to all managed font styles
const std::vector<Item> &get_styles() const;
const Item &get_activ_style() const; // TODO: rename to style
/// <summary>
/// Describe image in GPU to show settings of style
@ -140,25 +156,15 @@ public:
/// </summary>
struct Item
{
// define font, style and other property of text
FontItem font_item;
// cache for view font name with maximal width in imgui
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
std::optional<StyleImage> image;
};
};
// check if exist selected font style in manager
bool is_activ_font();
@ -168,35 +174,51 @@ public:
static float min_imgui_font_size;
static float max_imgui_font_size;
static float get_imgui_font_size(const FontProp& prop, const Emboss::FontFile& file);
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);
// load actual selected font
ImFont *create_imgui_font(size_t index, const std::string &text);
// must live same as imgui_font inside of atlas
ImVector<ImWchar> ranges = {};
bool load_active_font();
// Keep only actual style in atlas
ImFontAtlas atlas = {};
bool set_wx_font(size_t item_index, const wxFont &wx_font);
// getter on index selected font pointer for imgui
// text could extend font atlas when not in glyph range
ImFont *get_imgui_font(size_t item_index);
// wx widget font
std::optional<wxFont> wx_font = {};
// cache for view font name with maximal width in imgui
std::string truncated_name;
// 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
// NOTE: imgui_font has to be unused
// return true when extend range otherwise FALSE
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);
// Privat member
std::vector<Item> m_font_list;
size_t m_font_selected; // index to m_font_list
/// <summary>
/// Keep data needed to create Font Style Images in Job