Improve loading of default styles. Should fix issue on OSx

This commit is contained in:
Filip Sykala - NTB T15p 2023-01-30 17:44:14 +01:00
parent dac7b7e46a
commit 449267fa47
3 changed files with 115 additions and 76 deletions

View file

@ -124,7 +124,7 @@ GLGizmoEmboss::GLGizmoEmboss(GLCanvas3D &parent)
, m_volume(nullptr)
, m_is_unknown_font(false)
, 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(), create_default_styles)
, m_job_cancel(nullptr)
{
m_rotate_gizmo.set_group_id(0);
@ -1014,7 +1014,7 @@ void GLGizmoEmboss::initialize()
init_icons();
// initialize text styles
m_style_manager.init(wxGetApp().app_config, create_default_styles());
m_style_manager.init(wxGetApp().app_config);
set_default_text();
// Set rotation gizmo upwardrotate
@ -1025,20 +1025,48 @@ EmbossStyles GLGizmoEmboss::create_default_styles()
{
// https://docs.wxwidgets.org/3.0/classwx_font.html
// Predefined objects/pointers: wxNullFont, wxNORMAL_FONT, wxSMALL_FONT, wxITALIC_FONT, wxSWISS_FONT
return {
EmbossStyles styles = {
WxFontUtils::create_emboss_style(*wxNORMAL_FONT, _u8L("NORMAL")), // wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)
WxFontUtils::create_emboss_style(*wxSMALL_FONT, _u8L("SMALL")), // A font using the wxFONTFAMILY_SWISS family and 2 points smaller than wxNORMAL_FONT.
WxFontUtils::create_emboss_style(*wxITALIC_FONT, _u8L("ITALIC")), // A font using the wxFONTFAMILY_ROMAN family and wxFONTSTYLE_ITALIC style and of the same size of wxNORMAL_FONT.
WxFontUtils::create_emboss_style(*wxSWISS_FONT, _u8L("SWISS")), // A font identic to wxNORMAL_FONT except for the family used which is wxFONTFAMILY_SWISS.
WxFontUtils::create_emboss_style(wxFont(10, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD), _u8L("MODERN"))
WxFontUtils::create_emboss_style(wxFont(10, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD), _u8L("MODERN")),
};
}
// Could exist systems without installed font so last chance is used own file
//EmbossStyle GLGizmoEmboss::create_default_style() {
// std::string font_path = Slic3r::resources_dir() + "/fonts/NotoSans-Regular.ttf";
// return EmbossStyle{"Default font", font_path, EmbossStyle::Type::file_path};
//}
// Not all predefined font for wx must be valid TTF, but at least one style must be loadable
styles.erase(std::remove_if(styles.begin(), styles.end(), [](const EmbossStyle& style) {
wxFont wx_font = WxFontUtils::create_wxFont(style);
return WxFontUtils::create_font_file(wx_font) == nullptr;
}),styles.end()
);
// exist some valid style?
if (!styles.empty())
return styles;
// No valid style in defult list
// at least one style must contain loadable font
wxArrayString facenames = wxFontEnumerator::GetFacenames(wxFontEncoding::wxFONTENCODING_SYSTEM);
wxFont wx_font;
for (const wxString &face : facenames) {
wx_font = wxFont(face);
if (WxFontUtils::create_font_file(wx_font) != nullptr)
break;
wx_font = wxFont(); // NotOk
}
if (wx_font.IsOk()) {
// use first alphabetic sorted installed font
styles.push_back(WxFontUtils::create_emboss_style(wx_font, _u8L("First font")));
} else {
// On current OS is not installed any correct TTF font
// use font packed with Slic3r
std::string font_path = Slic3r::resources_dir() + "/fonts/NotoSans-Regular.ttf";
styles.push_back(EmbossStyle{_u8L("Default font"), font_path, EmbossStyle::Type::file_path});
}
return styles;
}
void GLGizmoEmboss::set_default_text(){ m_text = _u8L("Embossed text"); }
@ -3650,34 +3678,25 @@ std::string GLGizmoEmboss::get_file_name(const std::string &file_path)
DataBase priv::create_emboss_data_base(const std::string &text, StyleManager &style_manager, std::shared_ptr<std::atomic<bool>>& cancel)
{
auto create_volume_name = [&]() {
bool contain_enter = text.find('\n') != std::string::npos;
std::string text_fixed;
if (contain_enter) {
// change enters to space
text_fixed = text; // copy
std::replace(text_fixed.begin(), text_fixed.end(), '\n', ' ');
}
return ((contain_enter) ? text_fixed : text);
};
// create volume_name
std::string volume_name = text; // copy
// contain_enter?
if (volume_name.find('\n') != std::string::npos)
// change enters to space
std::replace(volume_name.begin(), volume_name.end(), '\n', ' ');
auto create_configuration = [&]() -> TextConfiguration {
if (!style_manager.is_active_font()) {
std::string default_text_for_emboss = _u8L("Embossed text");
EmbossStyle es = style_manager.get_style();
TextConfiguration tc{es, default_text_for_emboss};
// TODO: investigate how to initialize
return tc;
}
if (!style_manager.is_active_font())
style_manager.load_valid_style();
assert(style_manager.is_active_font());
EmbossStyle &es = style_manager.get_style();
// actualize font path - during changes in gui it could be corrupted
// volume must store valid path
assert(style_manager.get_wx_font().has_value());
assert(es.path.compare(WxFontUtils::store_wxFont(*style_manager.get_wx_font())) == 0);
// style.path = WxFontUtils::store_wxFont(*m_style_manager.get_wx_font());
return TextConfiguration{es, text};
};
const EmbossStyle &es = style_manager.get_style();
// actualize font path - during changes in gui it could be corrupted
// volume must store valid path
assert(style_manager.get_wx_font().has_value());
assert(style_manager.get_wx_font()->IsOk());
assert(es.path.compare(WxFontUtils::store_wxFont(*style_manager.get_wx_font())) == 0);
// style.path = WxFontUtils::store_wxFont(*m_style_manager.get_wx_font());
TextConfiguration tc{es, text};
// Cancel previous Job, when it is in process
// worker.cancel(); --> Use less in this case I want cancel only previous EmbossJob no other jobs
@ -3686,7 +3705,7 @@ DataBase priv::create_emboss_data_base(const std::string &text, StyleManager &st
cancel->store(true);
// create new shared ptr to cancel new job
cancel = std::make_shared<std::atomic<bool>>(false);
return Slic3r::GUI::Emboss::DataBase{style_manager.get_font_file_with_cache(), create_configuration(), create_volume_name(), cancel};
return Slic3r::GUI::Emboss::DataBase{style_manager.get_font_file_with_cache(), tc, volume_name, cancel};
}
void priv::start_create_object_job(DataBase &emboss_data, const Vec2d &coor)

View file

@ -14,8 +14,9 @@ using namespace Slic3r;
using namespace Slic3r::Emboss;
using namespace Slic3r::GUI::Emboss;
StyleManager::StyleManager(const ImWchar *language_glyph_range)
StyleManager::StyleManager(const ImWchar *language_glyph_range, std::function<EmbossStyles()> create_default_styles)
: m_imgui_init_glyph_range(language_glyph_range)
, m_create_default_styles(create_default_styles)
, m_exist_style_images(false)
, m_temp_style_images(nullptr)
, m_app_config(nullptr)
@ -27,13 +28,14 @@ StyleManager::~StyleManager() {
free_style_images();
}
void StyleManager::init(AppConfig *app_config, const EmbossStyles &default_styles)
void StyleManager::init(AppConfig *app_config)
{
m_app_config = app_config;
EmbossStyles styles = (app_config != nullptr) ?
EmbossStylesSerializable::load_styles(*app_config) :
default_styles;
if (styles.empty()) styles = default_styles;
EmbossStyles styles = (app_config != nullptr) ?
EmbossStylesSerializable::load_styles(*app_config) :
EmbossStyles{};
if (styles.empty())
styles = m_create_default_styles();
for (EmbossStyle &style : styles) {
make_unique_name(style.name);
m_style_items.push_back({style});
@ -48,23 +50,13 @@ void StyleManager::init(AppConfig *app_config, const EmbossStyles &default_style
if (active_index >= m_style_items.size()) active_index = 0;
// find valid font item
if (!load_style(active_index)) {
m_style_items.erase(m_style_items.begin() + active_index);
active_index = 0;
while (m_style_items.empty() || !load_style(active_index))
m_style_items.erase(m_style_items.begin());
// no one style from config is loadable
if (m_style_items.empty()) {
// set up default font list
for (EmbossStyle style : default_styles) {
make_unique_name(style.name);
m_style_items.push_back({std::move(style)});
}
// try to load first default font
[[maybe_unused]] bool loaded = load_style(active_index);
assert(loaded);
}
}
if (load_style(active_index))
return; // style is loaded
// Try to fix that style can't be loaded
m_style_items.erase(m_style_items.begin() + active_index);
load_valid_style();
}
bool StyleManager::store_styles_to_app_config(bool use_modification,
@ -135,7 +127,7 @@ void StyleManager::discard_style_changes() {
}
// try to save situation by load some font
load_first_valid_font();
load_valid_style();
}
void StyleManager::erase(size_t index) {
@ -161,6 +153,38 @@ void StyleManager::rename(const std::string& name) {
}
}
void StyleManager::load_valid_style()
{
// iterate over all known styles
while (!m_style_items.empty()) {
if (load_style(0))
return;
// can't load so erase it from list
m_style_items.erase(m_style_items.begin());
}
// no one style is loadable
// set up default font list
EmbossStyles def_style = m_create_default_styles();
for (EmbossStyle &style : def_style) {
make_unique_name(style.name);
m_style_items.push_back({std::move(style)});
}
// iterate over default styles
// There have to be option to use build in font
while (!m_style_items.empty()) {
if (load_style(0))
return;
// can't load so erase it from list
m_style_items.erase(m_style_items.begin());
}
// This OS doesn't have TTF as default font,
// find some loadable font out of default list
assert(false);
}
bool StyleManager::load_style(size_t style_index)
{
if (style_index >= m_style_items.size()) return false;
@ -206,15 +230,6 @@ bool StyleManager::load_style(const EmbossStyle &style, const wxFont &font)
bool StyleManager::is_active_font() { return m_style_cache.font_file.has_value(); }
bool StyleManager::load_first_valid_font() {
while (!m_style_items.empty()) {
if (load_style(0)) return true;
// can't load so erase it from list
m_style_items.erase(m_style_items.begin());
}
return false;
}
const EmbossStyle* StyleManager::get_stored_style() const
{
if (m_style_cache.style_index >= m_style_items.size()) return nullptr;

View file

@ -4,6 +4,7 @@
#include <memory>
#include <optional>
#include <string>
#include <functional>
#include <imgui/imgui.h>
#include <wx/font.h>
#include <GL/glew.h>
@ -23,7 +24,9 @@ class StyleManager
friend class CreateFontStyleImagesJob; // access to StyleImagesData
public:
StyleManager(const ImWchar *language_glyph_range);
/// <param name="language_glyph_range">Character to load for imgui when initialize imgui font</param>
/// <param name="create_default_styles">Function to create default styles</param>
StyleManager(const ImWchar *language_glyph_range, std::function<EmbossStyles()> create_default_styles);
/// <summary>
/// Release imgui font and style images from GPU
@ -36,8 +39,7 @@ public:
/// </summary>
/// <param name="app_config">Application configuration loaded from file "PrusaSlicer.ini"
/// + cfg is stored to privat variable</param>
/// <param name="default_styles">Used when list is not loadable from config</param>
void init(AppConfig *app_config, const EmbossStyles &default_styles);
void init(AppConfig *app_config);
/// <summary>
/// Write font list into AppConfig
@ -81,6 +83,11 @@ public:
/// <param name="name">New name</param>
void rename(const std::string &name);
/// <summary>
/// load some valid style
/// </summary>
void load_valid_style();
/// <summary>
/// Change active font
/// When font not loaded roll back activ font
@ -194,9 +201,7 @@ public:
static float get_imgui_font_size(const FontProp &prop, const Slic3r::Emboss::FontFile &file, double scale);
private:
// erase font when not possible to load
// used at initialize phaze - fonts could be modified in appConfig file by user
bool load_first_valid_font();
std::function<EmbossStyles()> m_create_default_styles;
/// <summary>
/// Cache data from style to reduce amount of: