mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-15 19:25:53 +08:00
Style select with rendered name
Fix negative volume color when dragging
This commit is contained in:
parent
c2608ce2fa
commit
137399ef1a
@ -31,6 +31,7 @@
|
||||
#include <wx/font.h>
|
||||
#include <wx/fontutil.h>
|
||||
#include <wx/fontdlg.h>
|
||||
#include <wx/fontenum.h>
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
@ -38,9 +39,12 @@
|
||||
//#define ALLOW_DEBUG_MODE
|
||||
#ifdef ALLOW_DEBUG_MODE
|
||||
#define ALLOW_ADD_FONT_BY_FILE
|
||||
#endif // ALLOW_DEBUG_MODE
|
||||
#define ALLOW_ADD_FONT_BY_OS_SELECTOR
|
||||
#define SHOW_IMGUI_ATLAS
|
||||
#endif // ALLOW_DEBUG_MODE
|
||||
|
||||
#define ALLOW_ADD_FONT_BY_FILE
|
||||
#define ALLOW_ADD_FONT_BY_OS_SELECTOR
|
||||
|
||||
using namespace Slic3r;
|
||||
using namespace Slic3r::GUI;
|
||||
@ -253,23 +257,37 @@ std::string GLGizmoEmboss::on_get_name() const { return _u8L("Emboss"); }
|
||||
void GLGizmoEmboss::on_render() {
|
||||
// no volume selected
|
||||
if (m_volume == nullptr) return;
|
||||
if (m_parent.get_selection().is_empty()) return;
|
||||
Selection &selection = m_parent.get_selection();
|
||||
if (selection.is_empty()) return;
|
||||
|
||||
if (m_temp_transformation.has_value()) {
|
||||
// draw text volume on temporary position
|
||||
const Selection &selection = m_parent.get_selection();
|
||||
const GLVolume& gl_volume = *selection.get_volume(*selection.get_volume_idxs().begin());
|
||||
glsafe(::glPushMatrix());
|
||||
glsafe(::glMultMatrixd(m_temp_transformation->data()));
|
||||
GLShaderProgram *shader = wxGetApp().get_shader("gouraud_light");
|
||||
shader->start_using();
|
||||
// dragging object must be selected so draw it with selected color
|
||||
shader->set_uniform("uniform_color", GLVolume::SELECTED_COLOR);
|
||||
|
||||
// dragging object must be selected so draw it with correct color
|
||||
//auto color = gl_volume.color;
|
||||
//auto color = gl_volume.render_color;
|
||||
auto color = GLVolume::SELECTED_COLOR;
|
||||
// Set transparent color for NEGATIVE_VOLUME & PARAMETER_MODIFIER
|
||||
|
||||
bool is_transparent = m_volume->type() != ModelVolumeType::MODEL_PART;
|
||||
if (is_transparent) {
|
||||
color[3] = 0.5f;
|
||||
glsafe(::glEnable(GL_BLEND));
|
||||
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
|
||||
}
|
||||
shader->set_uniform("uniform_color", color);
|
||||
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
gl_volume.indexed_vertex_array.render();
|
||||
glsafe(::glDisable(GL_DEPTH_TEST));
|
||||
|
||||
if (is_transparent) glsafe(::glDisable(GL_BLEND));
|
||||
|
||||
shader->stop_using();
|
||||
glsafe(::glPopMatrix());
|
||||
}
|
||||
@ -350,6 +368,9 @@ void GLGizmoEmboss::on_set_state()
|
||||
} else if (GLGizmoBase::m_state == GLGizmoBase::On) {
|
||||
if (!m_is_initialized) initialize();
|
||||
|
||||
// to reload fonts from system, when install new one
|
||||
wxFontEnumerator::InvalidateCache();
|
||||
|
||||
const Selection &selection = m_parent.get_selection();
|
||||
bool create_new_object = selection.is_empty();
|
||||
// When add Text on empty plate, Create new object with volume
|
||||
@ -421,9 +442,9 @@ void GLGizmoEmboss::initialize()
|
||||
|
||||
// calculate window size
|
||||
const ImGuiStyle &style = ImGui::GetStyle();
|
||||
float window_title = line_height + 2*style.FramePadding.y;// 21
|
||||
float input_height = line_height_with_spacing + 2*style.FramePadding.y; // 25
|
||||
float tree_header = line_height_with_spacing; // 19
|
||||
float window_title = line_height + 2*style.FramePadding.y;
|
||||
float input_height = line_height_with_spacing + 2*style.FramePadding.y;
|
||||
float tree_header = line_height_with_spacing;
|
||||
float window_height =
|
||||
window_title + // window title
|
||||
cfg.text_size.y + // text field
|
||||
@ -433,18 +454,20 @@ void GLGizmoEmboss::initialize()
|
||||
float window_width = cfg.combo_font_width + style.WindowPadding.x * 2;
|
||||
cfg.minimal_window_size = ImVec2(window_width, window_height);
|
||||
|
||||
// 94
|
||||
float addition_edit_height = input_height * 3 + tree_header;
|
||||
cfg.minimal_window_size_with_edit = ImVec2(cfg.minimal_window_size.x,
|
||||
cfg.minimal_window_size.y +
|
||||
addition_edit_height);
|
||||
|
||||
// 104
|
||||
float advance_height = input_height * 4;
|
||||
cfg.minimal_window_size_with_advance =
|
||||
ImVec2(cfg.minimal_window_size_with_edit.x,
|
||||
cfg.minimal_window_size_with_edit.y + advance_height);
|
||||
|
||||
cfg.min_style_image_height = line_height_with_spacing;
|
||||
cfg.max_style_image_width = cfg.max_font_name_width -
|
||||
2 * style.FramePadding.x;
|
||||
|
||||
m_gui_cfg.emplace(cfg);
|
||||
|
||||
// TODO: What to do when icon was NOT loaded? Generate them?
|
||||
@ -486,8 +509,7 @@ Slic3r::TriangleMesh GLGizmoEmboss::create_mesh()
|
||||
// It is neccessary to create some shape
|
||||
// Emboss text window is opened by creation new embosstext object
|
||||
std::shared_ptr<Emboss::FontFile>& font_file = m_font_manager.get_font_file();
|
||||
if (font_file == nullptr || m_font_manager.get_fonts().empty())
|
||||
return create_default_mesh();
|
||||
if (font_file == nullptr) return create_default_mesh();
|
||||
const FontItem &fi = m_font_manager.get_font_item();
|
||||
TriangleMesh result = create_mesh(m_text.c_str(), *font_file, fi.prop);
|
||||
if (result.its.empty()) return create_default_mesh();
|
||||
@ -637,6 +659,11 @@ void GLGizmoEmboss::draw_window()
|
||||
}
|
||||
}
|
||||
m_imgui->disabled_end();
|
||||
|
||||
#ifdef SHOW_IMGUI_ATLAS
|
||||
auto &atlas = m_font_manager.m_imgui_font_atlas;
|
||||
ImGui::Image(atlas.TexID, ImVec2(atlas.TexWidth, atlas.TexHeight));
|
||||
#endif // SHOW_IMGUI_ATLAS
|
||||
}
|
||||
|
||||
void GLGizmoEmboss::draw_text_input()
|
||||
@ -644,7 +671,7 @@ void GLGizmoEmboss::draw_text_input()
|
||||
static const ImGuiInputTextFlags flags =
|
||||
ImGuiInputTextFlags_AllowTabInput | ImGuiInputTextFlags_AutoSelectAll;
|
||||
|
||||
ImFont *imgui_font = m_font_manager.get_imgui_font();
|
||||
ImFont *imgui_font = m_font_manager.get_imgui_font(m_text);
|
||||
bool exist_font = imgui_font != nullptr && imgui_font->IsLoaded();
|
||||
if (exist_font) ImGui::PushFont(imgui_font);
|
||||
|
||||
@ -685,26 +712,29 @@ void GLGizmoEmboss::draw_text_input()
|
||||
|
||||
// Extend font ranges
|
||||
// imgui_font has to be unused
|
||||
if (exist_change) m_font_manager.get_imgui_font(m_text);
|
||||
if (exist_change) m_font_manager.clear_imgui_font();
|
||||
}
|
||||
|
||||
#include "wx/fontenum.h"
|
||||
void GLGizmoEmboss::draw_font_list()
|
||||
{
|
||||
class MyFontEnumerator : public wxFontEnumerator
|
||||
{
|
||||
wxArrayString m_facenames;
|
||||
wxFontEncoding m_encoding;
|
||||
bool m_fixed_width_only;
|
||||
bool m_is_init;
|
||||
public:
|
||||
MyFontEnumerator(wxFontEncoding encoding) : m_encoding(encoding), m_is_init(false){}
|
||||
MyFontEnumerator(wxFontEncoding encoding, bool fixed_width_only)
|
||||
: m_encoding(encoding)
|
||||
, m_fixed_width_only(fixed_width_only)
|
||||
, m_is_init(false)
|
||||
{}
|
||||
const wxArrayString& get_facenames() const{ return m_facenames; }
|
||||
bool is_init() const { return m_is_init; }
|
||||
bool init() {
|
||||
if (m_is_init) return false;
|
||||
m_is_init = true;
|
||||
bool fixedWidthOnly = false;
|
||||
if (!wxFontEnumerator::EnumerateFacenames(m_encoding, fixedWidthOnly)) return false;
|
||||
if (!wxFontEnumerator::EnumerateFacenames(m_encoding, m_fixed_width_only)) return false;
|
||||
if (m_facenames.empty()) return false;
|
||||
return true;
|
||||
}
|
||||
@ -720,7 +750,9 @@ void GLGizmoEmboss::draw_font_list()
|
||||
}
|
||||
};
|
||||
wxFontEncoding encoding = wxFontEncoding::wxFONTENCODING_SYSTEM;
|
||||
static MyFontEnumerator fontEnumerator(encoding);
|
||||
bool fixed_width_only = false;
|
||||
static MyFontEnumerator fontEnumerator(encoding, fixed_width_only);
|
||||
|
||||
std::optional<wxFont> &wx_font_opt = m_font_manager.get_wx_font();
|
||||
wxString actual_face_name = wx_font_opt.has_value() ?
|
||||
wx_font_opt->GetFaceName() : "";
|
||||
@ -729,14 +761,17 @@ void GLGizmoEmboss::draw_font_list()
|
||||
if (ImGui::BeginCombo("##font_selector", selected)) {
|
||||
if(!fontEnumerator.is_init()) fontEnumerator.init();
|
||||
const wxArrayString &face_names = fontEnumerator.get_facenames();
|
||||
//const wxArrayString &face_names = wxFontEnumerator::GetFacenames(encoding, fixed_width_only);
|
||||
ImGui::TextColored(ImGuiWrapper::COL_GREY_LIGHT, "count %d", static_cast<int>(face_names.size()));
|
||||
for (const wxString &face_name : face_names) {
|
||||
size_t index = &face_name - &face_names.front();
|
||||
ImGui::PushID(index);
|
||||
bool is_selected = (actual_face_name == face_name);
|
||||
if (ImGui::Selectable(face_name.ToUTF8().data(), is_selected)) {
|
||||
if (ImGui::Selectable(face_name.ToUTF8().data(), is_selected) &&
|
||||
wxFontEnumerator::IsValidFacename(face_name)) {
|
||||
// Select font
|
||||
wx_font_opt = wxFont(wxFontInfo().FaceName(face_name).Encoding(encoding));
|
||||
wxFont wx_font(wxFontInfo().FaceName(face_name).Encoding(encoding));
|
||||
m_font_manager.set_wx_font(wx_font);
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
@ -820,15 +855,15 @@ void GLGizmoEmboss::draw_model_type()
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoEmboss::draw_rename_style(const std::optional<size_t>& rename_index)
|
||||
void GLGizmoEmboss::draw_rename_style(bool start_rename)
|
||||
{
|
||||
// rename modal window popup
|
||||
const char * rename_popup_id = "Rename_font";
|
||||
static FontItem * rename_item;
|
||||
static std::string new_name;
|
||||
if (rename_index.has_value() && !ImGui::IsPopupOpen(rename_popup_id)) {
|
||||
if (start_rename && !ImGui::IsPopupOpen(rename_popup_id)) {
|
||||
ImGui::OpenPopup(rename_popup_id);
|
||||
rename_item = &m_font_manager.get_font(*rename_index).font_item;
|
||||
rename_item = &m_font_manager.get_font_item();
|
||||
new_name = rename_item->name; // initialize with original copy
|
||||
}
|
||||
|
||||
@ -852,12 +887,12 @@ void GLGizmoEmboss::draw_rename_style(const std::optional<size_t>& rename_index)
|
||||
bool allow_change = is_unique && !new_name.empty();
|
||||
|
||||
ImGuiInputTextFlags flags = ImGuiInputTextFlags_EnterReturnsTrue;
|
||||
if ((ImGui::InputText("##font name", &new_name, flags) &&
|
||||
allow_change) ||
|
||||
if ((ImGui::InputText("##font name", &new_name, flags) && allow_change) ||
|
||||
m_imgui->button(_L("ok"), ImVec2(0.f, 0.f), allow_change)) {
|
||||
rename_item->name = new_name;
|
||||
m_font_manager.get_truncated_name() = "";
|
||||
m_font_manager.free_style_images();
|
||||
ImGui::CloseCurrentPopup();
|
||||
store_font_list_to_app_config();
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
@ -865,52 +900,59 @@ void GLGizmoEmboss::draw_rename_style(const std::optional<size_t>& rename_index)
|
||||
|
||||
void GLGizmoEmboss::draw_style_list() {
|
||||
const float &max_width = m_gui_cfg->max_font_name_width;
|
||||
std::optional<size_t> rename_index, delete_index, duplicate_index;
|
||||
|
||||
std::optional<size_t> delete_index;
|
||||
const FontItem &actual_font_item = m_font_manager.get_font_item();
|
||||
std::string &trunc_name = m_font_manager.get_truncated_name();
|
||||
if (trunc_name.empty()) {
|
||||
// generate trunc name
|
||||
const std::string ¤t_name = actual_font_item.name;
|
||||
std::string trunc_name = ImGuiWrapper::trunc(current_name, max_width);
|
||||
const auto &fonts = m_font_manager.get_fonts();
|
||||
trunc_name = ImGuiWrapper::trunc(current_name, max_width);
|
||||
}
|
||||
|
||||
ImGui::Text("%s", _u8L("Style").c_str());
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(m_gui_cfg->combo_font_width);
|
||||
if (ImGui::BeginCombo("##style_selector", trunc_name.c_str())) {
|
||||
m_font_manager.init_style_images(m_gui_cfg->max_style_image_width);
|
||||
const auto &fonts = m_font_manager.get_fonts();
|
||||
for (const auto &item : fonts) {
|
||||
size_t index = &item - &fonts.front();
|
||||
const FontItem & fi = item.font_item;
|
||||
const std::string &actual_style_name = fi.name;
|
||||
ImGui::PushID(actual_style_name.c_str());
|
||||
std::string name_truncated = ImGuiWrapper::trunc(actual_style_name,
|
||||
max_width);
|
||||
std::string name_truncated =
|
||||
ImGuiWrapper::trunc(actual_style_name, max_width);
|
||||
|
||||
bool is_selected = (&fi == &actual_font_item);
|
||||
ImGuiSelectableFlags_ flags =
|
||||
ImGuiSelectableFlags_AllowItemOverlap; // allow click buttons
|
||||
if (ImGui::Selectable(name_truncated.c_str(), is_selected,
|
||||
flags)) {
|
||||
|
||||
const FontManager::StyleImage &img = *item.image;
|
||||
ImVec2 select_size(0.f, std::max(img.tex_size.y, m_gui_cfg->min_style_image_height));
|
||||
if (ImGui::Selectable("##style_select", is_selected, flags, select_size)) {
|
||||
if (m_font_manager.load_font(index)) process();
|
||||
} else if (ImGui::IsItemHovered())
|
||||
ImGui::SetTooltip("%s", actual_style_name.c_str());
|
||||
|
||||
// reorder items
|
||||
if (ImGui::IsItemActive() && !ImGui::IsItemHovered()) {
|
||||
int other_index = index +
|
||||
(ImGui::GetMouseDragDelta(0).y < 0.f ? -1 :
|
||||
1);
|
||||
if (other_index >= 0 && other_index < fonts.size()) {
|
||||
std::swap(m_font_manager.get_font(index),
|
||||
m_font_manager.get_font(other_index));
|
||||
// fix selected index
|
||||
if (is_selected)
|
||||
m_font_manager.select(other_index);
|
||||
else if (&fonts[other_index].font_item ==
|
||||
&actual_font_item)
|
||||
m_font_manager.select(index);
|
||||
std::optional<size_t> other_index;
|
||||
if (ImGui::GetMouseDragDelta(0).y < 0.f) {
|
||||
if (index > 0) other_index = index - 1;
|
||||
} else if ((index + 1) < fonts.size())
|
||||
other_index = index + 1;
|
||||
|
||||
if (other_index.has_value()) {
|
||||
m_font_manager.swap(index, *other_index);
|
||||
ImGui::ResetMouseDragDelta();
|
||||
}
|
||||
}
|
||||
|
||||
// draw style name
|
||||
ImGui::SameLine();
|
||||
ImGui::Image(img.texture_id, img.tex_size, img.uv0, img.uv1);
|
||||
|
||||
// delete button
|
||||
ImGui::SameLine(m_gui_cfg->delete_pos_x);
|
||||
if (draw_button(IconType::erase, is_selected) && !is_selected)
|
||||
delete_index = index;
|
||||
@ -925,31 +967,24 @@ void GLGizmoEmboss::draw_style_list() {
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
// delete font item
|
||||
if (delete_index.has_value())
|
||||
m_font_manager.erase(*delete_index);
|
||||
|
||||
ImGui::SameLine();
|
||||
if (draw_button(IconType::rename))
|
||||
rename_index = &m_font_manager.get_font() - &fonts.front();
|
||||
bool start_rename = false;
|
||||
if (draw_button(IconType::rename)) start_rename = true;
|
||||
if (ImGui::IsItemHovered())
|
||||
ImGui::SetTooltip("%s", _u8L("Rename actual style.").c_str());
|
||||
draw_rename_style(start_rename);
|
||||
|
||||
ImGui::SameLine();
|
||||
if (draw_button(IconType::duplicate))
|
||||
duplicate_index = &m_font_manager.get_font() - &fonts.front();
|
||||
m_font_manager.duplicate();
|
||||
|
||||
if (ImGui::IsItemHovered())
|
||||
ImGui::SetTooltip("%s", _u8L("Duplicate style.").c_str());
|
||||
|
||||
// duplicate font item
|
||||
if (duplicate_index.has_value()) {
|
||||
m_font_manager.duplicate(*duplicate_index);
|
||||
store_font_list_to_app_config();
|
||||
}
|
||||
|
||||
// delete font item
|
||||
if (delete_index.has_value()) {
|
||||
m_font_manager.erase(*delete_index);
|
||||
store_font_list_to_app_config();
|
||||
}
|
||||
|
||||
draw_rename_style(rename_index);
|
||||
|
||||
// TODO: Is style changed against stored one
|
||||
bool is_changed = false;
|
||||
@ -957,6 +992,8 @@ void GLGizmoEmboss::draw_style_list() {
|
||||
ImGui::SameLine();
|
||||
if (draw_button(IconType::save, !is_changed)) {
|
||||
// TODO: make save style
|
||||
store_font_list_to_app_config();
|
||||
//store_font_item_to_app_config();
|
||||
}
|
||||
if (ImGui::IsItemHovered())
|
||||
if (is_changed)
|
||||
@ -976,14 +1013,13 @@ void GLGizmoEmboss::draw_style_list() {
|
||||
|
||||
bool GLGizmoEmboss::italic_button()
|
||||
{
|
||||
FontManager::Item& item = m_font_manager.get_font();
|
||||
std::optional<wxFont> &wx_font = item.wx_font;
|
||||
std::optional<wxFont> &wx_font = m_font_manager.get_wx_font();
|
||||
if (!wx_font.has_value()) {
|
||||
draw_icon(IconType::italic, IconState::disabled);
|
||||
return false;
|
||||
}
|
||||
|
||||
std::optional<float> &skew = item.font_item.prop.skew;
|
||||
std::optional<float> &skew = m_font_manager.get_font_prop().skew;
|
||||
bool is_font_italic = skew.has_value() || WxFontUtils::is_italic(*wx_font);
|
||||
if (is_font_italic) {
|
||||
if (draw_button(IconType::unitalic)) {
|
||||
@ -995,7 +1031,8 @@ bool GLGizmoEmboss::italic_button()
|
||||
ImGui::SetTooltip("%s", _u8L("Unset italic").c_str());
|
||||
} else {
|
||||
if (draw_button(IconType::italic)) {
|
||||
std::shared_ptr<Emboss::FontFile> &font_file = item.font_file;
|
||||
std::shared_ptr<Emboss::FontFile> &font_file =
|
||||
m_font_manager.get_font_file();
|
||||
bool is_set = WxFontUtils::set_italic(*wx_font, font_file);
|
||||
// add skew when wxFont can't set it
|
||||
if (!is_set) skew = 0.2f;
|
||||
@ -1008,14 +1045,13 @@ bool GLGizmoEmboss::italic_button()
|
||||
}
|
||||
|
||||
bool GLGizmoEmboss::bold_button() {
|
||||
FontManager::Item & item = m_font_manager.get_font();
|
||||
std::optional<wxFont> &wx_font = item.wx_font;
|
||||
std::optional<wxFont> &wx_font = m_font_manager.get_wx_font();
|
||||
if (!wx_font.has_value()) {
|
||||
draw_icon(IconType::bold, IconState::disabled);
|
||||
return false;
|
||||
}
|
||||
|
||||
std::optional<float> &boldness = item.font_item.prop.boldness;
|
||||
std::optional<float> &boldness = m_font_manager.get_font_prop().boldness;
|
||||
bool is_font_bold = boldness.has_value() || WxFontUtils::is_bold(*wx_font);
|
||||
if (is_font_bold) {
|
||||
if (draw_button(IconType::unbold)) {
|
||||
@ -1027,7 +1063,8 @@ bool GLGizmoEmboss::bold_button() {
|
||||
ImGui::SetTooltip("%s", _u8L("Unset bold").c_str());
|
||||
} else {
|
||||
if (draw_button(IconType::bold)) {
|
||||
std::shared_ptr<Emboss::FontFile> &font_file = item.font_file;
|
||||
std::shared_ptr<Emboss::FontFile> &font_file =
|
||||
m_font_manager.get_font_file();
|
||||
bool is_set = WxFontUtils::set_bold(*wx_font, font_file);
|
||||
// add boldness when wxFont can't set it
|
||||
if (!is_set) boldness = 20.f;
|
||||
@ -1051,9 +1088,8 @@ void GLGizmoEmboss::draw_style_edit() {
|
||||
ImGui::SameLine();
|
||||
exist_change |= bold_button();
|
||||
|
||||
FontManager::Item &item = m_font_manager.get_font();
|
||||
FontItem & fi = item.font_item;
|
||||
std::optional<wxFont> &wx_font = item.wx_font;
|
||||
FontItem &fi = m_font_manager.get_font_item();
|
||||
std::optional<wxFont> &wx_font = m_font_manager.get_wx_font();
|
||||
|
||||
// TODO: should not be there
|
||||
// when actual font not loaded try to load
|
||||
@ -1066,7 +1102,10 @@ void GLGizmoEmboss::draw_style_edit() {
|
||||
ImGui::SameLine(m_gui_cfg->style_edit_text_width);
|
||||
ImGui::SetNextItemWidth(m_gui_cfg->combo_font_width);
|
||||
if (ImGui::InputFloat("##line height", &font_prop.size_in_mm, 0.1f, 1.f, "%.1f mm")) {
|
||||
if (font_prop.size_in_mm < 0.1) font_prop.size_in_mm = 10;
|
||||
// size can't be zero or negative
|
||||
if (font_prop.size_in_mm < std::numeric_limits<float>::epsilon())
|
||||
font_prop.size_in_mm = 10.f;
|
||||
|
||||
// store font size into path
|
||||
if (fi.type == WxFontUtils::get_actual_type()) {
|
||||
if (wx_font.has_value()) {
|
||||
@ -1075,13 +1114,11 @@ void GLGizmoEmboss::draw_style_edit() {
|
||||
fi.path = WxFontUtils::store_wxFont(*wx_font);
|
||||
}
|
||||
}
|
||||
m_font_manager.load_imgui_font(m_text);
|
||||
exist_change = true;
|
||||
}
|
||||
if (exist_change) {
|
||||
std::shared_ptr<Emboss::FontFile> &font_file = item.font_file;
|
||||
font_file->cache.clear();
|
||||
store_font_item_to_app_config();
|
||||
m_font_manager.clear_imgui_font();
|
||||
m_font_manager.free_style_images();
|
||||
process();
|
||||
}
|
||||
|
||||
@ -1109,14 +1146,13 @@ void GLGizmoEmboss::draw_advanced()
|
||||
return;
|
||||
}
|
||||
|
||||
FontItem &fi = m_font_manager.get_font_item();
|
||||
FontProp &font_prop = fi.prop;
|
||||
FontProp &font_prop = m_font_manager.get_font_item().prop;
|
||||
bool exist_change = false;
|
||||
|
||||
ImGui::SetNextItemWidth(2 * m_gui_cfg->advanced_input_width);
|
||||
if (ImGuiWrapper::input_optional_int(_u8L("CharGap[in font points]").c_str(), font_prop.char_gap)) {
|
||||
font_file->cache.clear();
|
||||
m_font_manager.load_imgui_font(m_text);
|
||||
// char gap is stored inside of imgui font atlas
|
||||
m_font_manager.clear_imgui_font();
|
||||
exist_change = true;
|
||||
}
|
||||
|
||||
@ -1125,28 +1161,24 @@ void GLGizmoEmboss::draw_advanced()
|
||||
exist_change = true;
|
||||
|
||||
ImGui::SetNextItemWidth(2 * m_gui_cfg->advanced_input_width);
|
||||
if (m_imgui->slider_optional_float(_u8L("Boldness [in font points]").c_str(), font_prop.boldness, -200.f, 200.f, "%.0f", 1.f, false, _L("tiny / wide chars"))){
|
||||
font_file->cache.clear();
|
||||
if (m_imgui->slider_optional_float(_u8L("Boldness [in font points]").c_str(), font_prop.boldness, -200.f, 200.f, "%.0f", 1.f, false, _L("tiny / wide chars")))
|
||||
exist_change = true;
|
||||
}
|
||||
|
||||
|
||||
ImGui::SetNextItemWidth(2 * m_gui_cfg->advanced_input_width);
|
||||
if (m_imgui->slider_optional_float(_u8L("Italic [Skew ratio]").c_str(), font_prop.skew, -1.f, 1.f, "%.2f", 1.f, false, _L("italic strength"))){
|
||||
font_file->cache.clear();
|
||||
if (m_imgui->slider_optional_float(_u8L("Italic [Skew ratio]").c_str(), font_prop.skew, -1.f, 1.f, "%.2f", 1.f, false, _L("italic strength")))
|
||||
exist_change = true;
|
||||
}
|
||||
|
||||
// when more collection add selector
|
||||
if (font_file != nullptr && font_file->count > 1) {
|
||||
if (font_file->count > 1) {
|
||||
ImGui::SetNextItemWidth(m_gui_cfg->advanced_input_width);
|
||||
if (ImGui::BeginCombo(_u8L("Font collection").c_str(),
|
||||
std::to_string(font_file->index).c_str())) {
|
||||
for (unsigned int i = 0; i < font_file->count; ++i) {
|
||||
ImGui::PushID(1 << (10 + i));
|
||||
if (ImGui::Selectable(std::to_string(i).c_str(),
|
||||
i == font_file->index)) {
|
||||
bool is_selected = i == font_file->index;
|
||||
if (ImGui::Selectable(std::to_string(i).c_str(), is_selected)) {
|
||||
font_file->index = i;
|
||||
font_file->cache.clear();
|
||||
exist_change = true;
|
||||
}
|
||||
ImGui::PopID();
|
||||
@ -1156,12 +1188,9 @@ void GLGizmoEmboss::draw_advanced()
|
||||
}
|
||||
|
||||
if (exist_change) {
|
||||
store_font_item_to_app_config();
|
||||
m_font_manager.free_style_images();
|
||||
process();
|
||||
}
|
||||
|
||||
auto& atlas = m_font_manager.m_imgui_font_atlas;
|
||||
ImGui::Image(atlas.TexID, ImVec2(atlas.TexWidth, atlas.TexHeight));
|
||||
#ifdef ALLOW_DEBUG_MODE
|
||||
ImGui::Text("family = %s", (font_prop.family.has_value() ?
|
||||
font_prop.family->c_str() :
|
||||
@ -1275,9 +1304,10 @@ bool GLGizmoEmboss::choose_true_type_file()
|
||||
|
||||
// set first valid added font as active
|
||||
if (!font_loaded) {
|
||||
if (!m_font_manager.load_font(m_font_manager.get_fonts().size() - 1)) {
|
||||
//m_font_list.pop_back();
|
||||
} else
|
||||
size_t index = m_font_manager.get_fonts().size() - 1;
|
||||
if (!m_font_manager.load_font(index))
|
||||
m_font_manager.erase(index);
|
||||
else
|
||||
font_loaded = true;
|
||||
}
|
||||
}
|
||||
@ -1321,6 +1351,13 @@ bool GLGizmoEmboss::choose_svg_file()
|
||||
|
||||
TextConfiguration GLGizmoEmboss::create_configuration()
|
||||
{
|
||||
FontItem &fi = m_font_manager.get_font_item();
|
||||
// actualize font path
|
||||
if (fi.type == WxFontUtils::get_actual_type()) {
|
||||
std::optional<wxFont> &wx_font = m_font_manager.get_wx_font();
|
||||
if (wx_font.has_value())
|
||||
fi.path = WxFontUtils::store_wxFont(*wx_font);
|
||||
}
|
||||
return TextConfiguration(m_font_manager.get_font_item(), m_text);
|
||||
}
|
||||
|
||||
|
@ -103,7 +103,7 @@ private:
|
||||
void draw_text_input();
|
||||
void draw_model_type();
|
||||
void draw_style_list();
|
||||
void draw_rename_style(const std::optional<size_t>& rename_index);
|
||||
void draw_rename_style(bool start_rename);
|
||||
void draw_font_list();
|
||||
void draw_style_edit();
|
||||
bool italic_button();
|
||||
@ -147,6 +147,9 @@ private:
|
||||
float max_font_name_width = 0.f;
|
||||
float icon_width = 0.f;
|
||||
|
||||
float min_style_image_height = 0.f;
|
||||
int max_style_image_width = 0.f;
|
||||
|
||||
float style_edit_text_width = 0.f;
|
||||
|
||||
ImVec2 text_size;
|
||||
|
@ -10,19 +10,29 @@ 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(0)
|
||||
: m_imgui_init_glyph_range(language_glyph_range)
|
||||
, m_font_selected(std::numeric_limits<size_t>::max())
|
||||
, m_exist_style_images(false)
|
||||
{}
|
||||
|
||||
FontManager::~FontManager() {
|
||||
free_imgui_fonts();
|
||||
free_style_images();
|
||||
}
|
||||
|
||||
void FontManager::select(size_t index)
|
||||
{
|
||||
if (index < m_font_list.size())
|
||||
m_font_selected = index;
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
@ -35,6 +45,7 @@ void FontManager::duplicate(size_t index) {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -46,7 +57,9 @@ void FontManager::erase(size_t index) {
|
||||
IM_DELETE(imgui_font);
|
||||
|
||||
m_font_list.erase(m_font_list.begin() + index);
|
||||
|
||||
// fix selected index
|
||||
if (!is_activ_font()) return;
|
||||
if (index < m_font_selected) --m_font_selected;
|
||||
}
|
||||
|
||||
@ -54,7 +67,7 @@ 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_font();
|
||||
bool is_loaded = load_activ_font();
|
||||
if (!is_loaded) std::swap(font_index, m_font_selected);
|
||||
return is_loaded;
|
||||
}
|
||||
@ -62,9 +75,8 @@ bool FontManager::load_font(size_t font_index)
|
||||
bool FontManager::load_font(size_t font_index, const wxFont &font)
|
||||
{
|
||||
if (font_index >= m_font_list.size()) return false;
|
||||
m_font_list[font_index].wx_font = font;
|
||||
std::swap(font_index, m_font_selected);
|
||||
bool is_loaded = load_font(font);
|
||||
bool is_loaded = set_wx_font(font);
|
||||
if (!is_loaded) std::swap(font_index, m_font_selected);
|
||||
return is_loaded;
|
||||
}
|
||||
@ -78,44 +90,22 @@ static std::string get_file_name(const std::string &file_path)
|
||||
return file_path.substr(offset, count);
|
||||
}
|
||||
|
||||
bool FontManager::load_font()
|
||||
bool FontManager::load_activ_font()
|
||||
{
|
||||
// next condition may be safely removed
|
||||
if (m_font_selected >= m_font_list.size()) return false;
|
||||
|
||||
Item &item = m_font_list[m_font_selected];
|
||||
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::load_font(
|
||||
fi.path.c_str());
|
||||
if (font_ptr == nullptr) return false;
|
||||
item.font_file = std::move(font_ptr);
|
||||
load_imgui_font();
|
||||
return true;
|
||||
return set_up_font_file(m_font_selected);
|
||||
}
|
||||
if (fi.type != WxFontUtils::get_actual_type()) return false;
|
||||
item.wx_font = WxFontUtils::load_wxFont(fi.path);
|
||||
if (!item.wx_font.has_value()) return false;
|
||||
|
||||
// fill font name after load from .3mf
|
||||
if (fi.name.empty())
|
||||
fi.name = WxFontUtils::get_human_readable_name(*item.wx_font);
|
||||
return load_font(*item.wx_font);
|
||||
bool FontManager::is_activ_font() {
|
||||
return m_font_selected < m_font_list.size();
|
||||
}
|
||||
|
||||
bool FontManager::load_first_valid_font() {
|
||||
// try to load valid font
|
||||
m_font_selected = 0;
|
||||
bool is_font_loaded = load_font();
|
||||
while (!is_font_loaded && !m_font_list.empty()) {
|
||||
while (!m_font_list.empty()) {
|
||||
if (load_font(0)) return true;
|
||||
// can't load so erase it from list
|
||||
m_font_list.erase(m_font_list.begin());
|
||||
is_font_loaded = load_font();
|
||||
}
|
||||
return !m_font_list.empty();
|
||||
return false;
|
||||
}
|
||||
|
||||
void FontManager::add_font(FontItem font_item)
|
||||
@ -135,25 +125,28 @@ void FontManager::add_fonts(FontList font_list)
|
||||
std::shared_ptr<Emboss::FontFile> &FontManager::get_font_file()
|
||||
{
|
||||
// TODO: fix not selected font
|
||||
//if (m_font_selected >= m_font_list.size()) return nullptr;
|
||||
//if (!is_activ_font()) return nullptr;
|
||||
return m_font_list[m_font_selected].font_file;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -165,7 +158,26 @@ FontProp &FontManager::get_font_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
|
||||
@ -173,6 +185,15 @@ const std::optional<wxFont> &FontManager::get_wx_font() const
|
||||
return m_font_list[m_font_selected].wx_font;
|
||||
}
|
||||
|
||||
void FontManager::clear_imgui_font() {
|
||||
// TODO: improove to clear only actual font
|
||||
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(const std::string &text)
|
||||
{
|
||||
return get_imgui_font(m_font_selected, text);
|
||||
@ -180,12 +201,11 @@ ImFont *FontManager::get_imgui_font(const std::string &text)
|
||||
|
||||
ImFont *FontManager::get_imgui_font(size_t item_index, const std::string &text)
|
||||
{
|
||||
// is selected font
|
||||
if (item_index >= m_font_list.size()) return nullptr;
|
||||
|
||||
Item &item = m_font_list[item_index];
|
||||
// check is already loaded
|
||||
if (!item.imgui_font_index.has_value()) return nullptr;
|
||||
if (!item.imgui_font_index.has_value())
|
||||
return load_imgui_font(item_index, text);
|
||||
|
||||
size_t index = *item.imgui_font_index;
|
||||
auto & fonts = m_imgui_font_atlas.Fonts;
|
||||
|
||||
@ -194,7 +214,7 @@ ImFont *FontManager::get_imgui_font(size_t item_index, const std::string &text)
|
||||
if (index >= fonts.size()) return nullptr;
|
||||
ImFont *font = fonts[index];
|
||||
if (font == nullptr) return nullptr;
|
||||
|
||||
if (!font->IsLoaded()) return nullptr;
|
||||
if (!text.empty() && !is_text_in_ranges(font, text))
|
||||
extend_imgui_font_range(item_index, text);
|
||||
|
||||
@ -217,32 +237,13 @@ const std::vector<FontManager::Item> &FontManager::get_fonts() const
|
||||
return m_font_list;
|
||||
}
|
||||
|
||||
std::vector<FontManager::Item> &FontManager::get_fonts()
|
||||
{
|
||||
return m_font_list;
|
||||
}
|
||||
|
||||
const FontManager::Item &FontManager::get_font() const
|
||||
{
|
||||
return m_font_list[m_font_selected];
|
||||
}
|
||||
|
||||
FontManager::Item &FontManager::get_font()
|
||||
void FontManager::make_unique_name(std::string &name)
|
||||
{
|
||||
return m_font_list[m_font_selected];
|
||||
}
|
||||
|
||||
FontManager::Item &FontManager::get_font(size_t index)
|
||||
{
|
||||
return m_font_list[index];
|
||||
}
|
||||
|
||||
const FontManager::Item &FontManager::get_font(size_t index) const
|
||||
{
|
||||
return m_font_list[index];
|
||||
}
|
||||
|
||||
void FontManager::make_unique_name(std::string &name) {
|
||||
auto is_unique = [&](const std::string &name) -> bool {
|
||||
for (const Item &it : m_font_list)
|
||||
if (it.font_item.name == name) return false;
|
||||
@ -266,6 +267,26 @@ 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::load_font(
|
||||
fi.path.c_str());
|
||||
if (font_ptr == nullptr) return false;
|
||||
item.font_file = 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);
|
||||
}
|
||||
|
||||
bool FontManager::is_text_in_ranges(const ImFont *font, const std::string &text)
|
||||
{
|
||||
if (font == nullptr) return false;
|
||||
@ -312,6 +333,162 @@ void FontManager::extend_imgui_font_range(size_t index, const std::string& text)
|
||||
load_imgui_font(index, text);
|
||||
}
|
||||
|
||||
#include "libslic3r/SLA/AGGRaster.hpp"
|
||||
void FontManager::create_texture(size_t index, const std::string &text, GLuint& tex_id, ImVec2& tex_size)
|
||||
{
|
||||
if (index >= m_font_list.size()) return;
|
||||
Item &item = m_font_list[index];
|
||||
const FontProp &font_prop = item.font_item.prop;
|
||||
std::shared_ptr<Emboss::FontFile> &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);
|
||||
|
||||
BoundingBox bb;
|
||||
for (ExPolygon &shape : shapes) bb.merge(BoundingBox(shape.contour.points));
|
||||
for (ExPolygon &shape : shapes) shape.translate(-bb.min);
|
||||
|
||||
double scale = font_prop.size_in_mm;
|
||||
BoundingBoxf bb2 = unscaled(bb);
|
||||
bb2.scale(scale);
|
||||
tex_size.x = bb2.max.x() - bb2.min.x();
|
||||
tex_size.y = bb2.max.y() - bb2.min.y();
|
||||
sla::RasterBase::Resolution resolution(tex_size.x,tex_size.y);
|
||||
sla::RasterBase::PixelDim dim(1/scale, 1/scale);
|
||||
const double no_gamma = 1.;
|
||||
std::unique_ptr<sla::RasterBase> r =
|
||||
sla::create_raster_grayscale_aa(resolution, dim, no_gamma);
|
||||
for (const ExPolygon &shape : shapes) r->draw(shape);
|
||||
// reserve texture on GPU
|
||||
glGenTextures(1, &tex_id);
|
||||
glBindTexture(GL_TEXTURE_2D, tex_id);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
sla::RasterEncoder encoder = [](const void *ptr, size_t w, size_t h, size_t num_components) -> sla::EncodedRaster {
|
||||
GLsizei width = w, height = h;
|
||||
GLint border = 0;
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, border, GL_ALPHA, GL_UNSIGNED_BYTE, ptr);
|
||||
return sla::EncodedRaster();
|
||||
};
|
||||
r->encode(encoder);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
void FontManager::init_style_images(int max_width) {
|
||||
// check already initialized
|
||||
if (m_exist_style_images) return;
|
||||
|
||||
// create shapes and calc size (bounding boxes)
|
||||
std::vector<ExPolygons> name_shapes(m_font_list.size());
|
||||
for (Item &item : m_font_list) {
|
||||
FontItem & font_item = item.font_item;
|
||||
const FontProp & font_prop = font_item.prop;
|
||||
std::shared_ptr<Emboss::FontFile> &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;
|
||||
|
||||
ExPolygons &shapes = name_shapes[index];
|
||||
shapes = Emboss::text2shapes(*font_file, font_item.name.c_str(), font_prop);
|
||||
// create image description
|
||||
item.image = StyleImage();
|
||||
StyleImage &image = *item.image;
|
||||
|
||||
BoundingBox &bounding_box = image.bounding_box;
|
||||
for (ExPolygon &shape : shapes)
|
||||
bounding_box.merge(BoundingBox(shape.contour.points));
|
||||
for (ExPolygon &shape : shapes) shape.translate(-bounding_box.min);
|
||||
|
||||
double scale = font_prop.size_in_mm;
|
||||
BoundingBoxf bb2 = unscaled(bounding_box);
|
||||
bb2.scale(scale);
|
||||
image.tex_size.x = bb2.max.x() - bb2.min.x();
|
||||
image.tex_size.y = bb2.max.y() - bb2.min.y();
|
||||
// crop image width
|
||||
if (image.tex_size.x > max_width)
|
||||
image.tex_size.x = max_width;
|
||||
}
|
||||
|
||||
// arrange bounding boxes
|
||||
int offset_y = 0;
|
||||
int width = 0;
|
||||
for (Item &item : m_font_list) {
|
||||
StyleImage &image = *item.image;
|
||||
image.offset.y() = offset_y;
|
||||
offset_y += image.tex_size.y+1;
|
||||
if (width < image.tex_size.x)
|
||||
width = image.tex_size.x;
|
||||
}
|
||||
int height = offset_y;
|
||||
for (Item &item : m_font_list) {
|
||||
StyleImage &image = *item.image;
|
||||
const Point &o = image.offset;
|
||||
const ImVec2 &s = image.tex_size;
|
||||
image.uv0 = ImVec2(o.x() / (double) width,
|
||||
o.y() / (double) height);
|
||||
image.uv1 = ImVec2((o.x() + s.x) / (double) width,
|
||||
(o.y() + s.y) / (double) height);
|
||||
}
|
||||
|
||||
// reserve texture on GPU
|
||||
GLuint tex_id;
|
||||
GLenum target = GL_TEXTURE_2D, format = GL_ALPHA, type = GL_UNSIGNED_BYTE;
|
||||
GLint level = 0, border = 0;
|
||||
glsafe(::glGenTextures(1, &tex_id));
|
||||
glsafe(::glBindTexture(target, tex_id));
|
||||
glsafe(::glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
|
||||
glsafe(::glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
|
||||
// texture size
|
||||
GLint w = width, h = height;
|
||||
glsafe(::glTexImage2D(target, level, GL_ALPHA, w, h, border, format, type, nullptr));
|
||||
|
||||
// set up texture id
|
||||
void *texture_id = (void *)(intptr_t) tex_id;
|
||||
for (Item &item : m_font_list) item.image->texture_id = texture_id;
|
||||
|
||||
// upload sub textures
|
||||
for (Item &item : m_font_list) {
|
||||
double scale = item.font_item.prop.size_in_mm;
|
||||
StyleImage &image = *item.image;
|
||||
sla::RasterBase::Resolution resolution(image.tex_size.x, image.tex_size.y);
|
||||
sla::RasterBase::PixelDim dim(1 / scale, 1 / scale);
|
||||
double gamma = 1.;
|
||||
std::unique_ptr<sla::RasterBase> r = sla::create_raster_grayscale_aa(resolution, dim, gamma);
|
||||
size_t index = &item - &m_font_list.front();
|
||||
for (const ExPolygon &shape : name_shapes[index]) r->draw(shape);
|
||||
const Point& offset = image.offset;
|
||||
sla::RasterEncoder encoder =
|
||||
[offset, target, level, format, type]
|
||||
(const void *ptr, size_t w, size_t h, size_t num_components) {
|
||||
GLint sub_w = w, sub_h = h, xoffset = offset.x(), yoffset = offset.y();
|
||||
glsafe(::glTexSubImage2D(target, level, xoffset, yoffset, sub_w, sub_h, format, type, ptr));
|
||||
return sla::EncodedRaster();
|
||||
};
|
||||
// upload texture data to GPU
|
||||
r->encode(encoder);
|
||||
}
|
||||
|
||||
// bind default texture
|
||||
GLuint no_texture_id = 0;
|
||||
glsafe(::glBindTexture(target, no_texture_id));
|
||||
|
||||
m_exist_style_images = true;
|
||||
}
|
||||
|
||||
void FontManager::free_style_images() {
|
||||
std::shared_ptr<Emboss::FontFile> &font_file =
|
||||
m_font_list[m_font_selected].font_file;
|
||||
if(font_file != nullptr)
|
||||
font_file->cache.clear();
|
||||
|
||||
if (!m_exist_style_images) return;
|
||||
GLuint tex_id = (GLuint) (intptr_t) m_font_list.front().image->texture_id;
|
||||
for (Item &it : m_font_list) it.image.reset();
|
||||
|
||||
glsafe(::glDeleteTextures(1, &tex_id));
|
||||
m_exist_style_images = false;
|
||||
}
|
||||
|
||||
|
||||
void FontManager::free_imgui_fonts()
|
||||
{
|
||||
for (auto &item : m_font_list)
|
||||
@ -319,26 +496,13 @@ void FontManager::free_imgui_fonts()
|
||||
m_imgui_font_atlas.Clear();
|
||||
}
|
||||
|
||||
bool FontManager::load_font(const wxFont &font)
|
||||
{
|
||||
std::unique_ptr<Emboss::FontFile> font_ptr = WxFontUtils::load_font(font);
|
||||
if (font_ptr == nullptr) return false;
|
||||
m_font_list[m_font_selected].font_file = std::move(font_ptr);
|
||||
load_imgui_font();
|
||||
return true;
|
||||
}
|
||||
|
||||
void FontManager::load_imgui_font(const std::string &text) {
|
||||
load_imgui_font(m_font_selected, text);
|
||||
}
|
||||
|
||||
void FontManager::load_imgui_font(size_t index, const std::string &text)
|
||||
ImFont * FontManager::load_imgui_font(size_t index, const std::string &text)
|
||||
{
|
||||
free_imgui_fonts(); // TODO: remove it after correct initialization
|
||||
|
||||
if (index >= m_font_list.size()) return;
|
||||
if (index >= m_font_list.size()) return nullptr;
|
||||
Item &item = m_font_list[index];
|
||||
if (item.font_file == nullptr) return;
|
||||
if (item.font_file == nullptr) return nullptr;
|
||||
const Emboss::FontFile &font_file = *item.font_file;
|
||||
|
||||
// TODO: Create glyph range
|
||||
@ -399,6 +563,27 @@ void FontManager::load_imgui_font(size_t index, const std::string &text)
|
||||
// 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;
|
||||
if (m_imgui_font_atlas.Fonts.empty()) return nullptr;
|
||||
item.imgui_font_index = m_imgui_font_atlas.Fonts.size() - 1;
|
||||
return m_imgui_font_atlas.Fonts.back();
|
||||
}
|
||||
|
||||
bool FontManager::set_wx_font(size_t item_index, 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 = 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);
|
||||
|
||||
clear_imgui_font();
|
||||
return true;
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include <optional>
|
||||
#include <imgui/imgui.h>
|
||||
#include <GL/glew.h>
|
||||
#include "libslic3r/Emboss.hpp"
|
||||
|
||||
class wxFont;
|
||||
@ -13,6 +14,7 @@ namespace Slic3r::GUI {
|
||||
/// GUI list of loaded fonts
|
||||
/// Keep pointer to ImGui font pointers
|
||||
/// Keep file data of TTF files
|
||||
/// Cache wx font objects
|
||||
/// </summary>
|
||||
class FontManager
|
||||
{
|
||||
@ -20,21 +22,41 @@ public:
|
||||
FontManager(const ImWchar *language_glyph_range);
|
||||
~FontManager();
|
||||
|
||||
void select(size_t index);
|
||||
void duplicate(size_t index);
|
||||
/// <summary>
|
||||
/// Change order of style item in m_font_list.
|
||||
/// Fix selected font index when (i1 || i2) == m_font_selected
|
||||
/// </summary>
|
||||
/// <param name="i1">First index to m_font_list</param>
|
||||
/// <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
|
||||
/// </summary>
|
||||
/// <param name="index">Index of style to be removed</param>
|
||||
void erase(size_t index);
|
||||
|
||||
// load actual selected font
|
||||
bool load_font();
|
||||
// try to select and load font_index
|
||||
/// <summary>
|
||||
/// Change active font
|
||||
/// When font not loaded roll back activ font
|
||||
/// </summary>
|
||||
/// <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);
|
||||
// fastering load font on index by wxFont
|
||||
// fastering load font on index by wxFont, ignore type and descriptor
|
||||
bool load_font(size_t font_index, const wxFont &font);
|
||||
|
||||
void load_imgui_font(const std::string &text = "");
|
||||
void load_imgui_font(size_t index, const std::string &text);
|
||||
// remove cached imgui font for actual selected font
|
||||
void clear_imgui_font();
|
||||
|
||||
// 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();
|
||||
|
||||
// add font into manager
|
||||
@ -57,26 +79,41 @@ public:
|
||||
const std::optional<wxFont> &get_wx_font() const;
|
||||
std::optional<wxFont> &get_wx_font();
|
||||
|
||||
// getter on acitve font pointer for imgui
|
||||
// text could extend font atlas when not in glyph range
|
||||
ImFont *get_imgui_font(const std::string &text = "");
|
||||
// setter of font for actual selection
|
||||
bool set_wx_font(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, const std::string &text = "");
|
||||
// Getter for cached trucated name for style list selector
|
||||
std::string &get_truncated_name();
|
||||
|
||||
// Getter on acitve font pointer for imgui
|
||||
// Initialize imgui font(generate texture) when doesn't exist yet.
|
||||
// Extend font atlas when not in glyph range
|
||||
ImFont *get_imgui_font(const std::string &text);
|
||||
|
||||
// free used memory and font file data
|
||||
void free_except_active_font();
|
||||
|
||||
/// <summary>
|
||||
/// initialization texture with rendered font style
|
||||
/// </summary>
|
||||
void init_style_images(int max_width);
|
||||
void free_style_images();
|
||||
|
||||
void create_texture(size_t font_index, const std::string &text, GLuint& tex_id, ImVec2& tex_size);
|
||||
|
||||
struct Item;
|
||||
// access to all managed fonts
|
||||
const std::vector<Item> &get_fonts() const;
|
||||
|
||||
std::vector<Item> &get_fonts();
|
||||
const Item &get_font() const;
|
||||
Item &get_font();
|
||||
const Item &get_font(size_t index) const;
|
||||
Item &get_font(size_t index);
|
||||
|
||||
struct StyleImage
|
||||
{
|
||||
void* texture_id = 0; // GLuint
|
||||
BoundingBox bounding_box;
|
||||
ImVec2 tex_size, uv0, uv1;
|
||||
Point offset = Point(0, 0);
|
||||
StyleImage() = default;
|
||||
};
|
||||
|
||||
struct Item
|
||||
{
|
||||
@ -95,12 +132,29 @@ public:
|
||||
|
||||
// wx widget font
|
||||
std::optional<wxFont> wx_font;
|
||||
|
||||
// visualization of style
|
||||
std::optional<StyleImage> image;
|
||||
};
|
||||
|
||||
// TODO: make private
|
||||
ImFontAtlas m_imgui_font_atlas;
|
||||
|
||||
bool is_activ_font();
|
||||
|
||||
private:
|
||||
void duplicate(size_t index);
|
||||
// load actual selected font
|
||||
ImFont *load_imgui_font(size_t index, const std::string &text);
|
||||
|
||||
bool load_activ_font();
|
||||
|
||||
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, const std::string &text = "");
|
||||
|
||||
// extend actual imgui font when exist unknown char in text
|
||||
// NOTE: imgui_font has to be unused
|
||||
void extend_imgui_font_range(size_t font_index, const std::string &text);
|
||||
@ -121,8 +175,7 @@ private:
|
||||
int max_imgui_font_size = 60;
|
||||
} m_cfg;
|
||||
|
||||
// load actual font by wx font
|
||||
bool load_font(const wxFont &font);
|
||||
bool set_up_font_file(size_t item_index);
|
||||
|
||||
void make_unique_name(std::string &name);
|
||||
|
||||
@ -130,6 +183,8 @@ private:
|
||||
std::vector<Item> m_font_list;
|
||||
size_t m_font_selected; // index to m_font_list
|
||||
|
||||
bool m_exist_style_images;
|
||||
|
||||
// store all font GLImages
|
||||
//ImFontAtlas m_imgui_font_atlas;
|
||||
const ImWchar *m_imgui_init_glyph_range;
|
||||
|
@ -30,7 +30,7 @@ void *WxFontUtils::can_load(const wxFont &font)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<Emboss::FontFile> WxFontUtils::load_font(const wxFont &font)
|
||||
std::unique_ptr<Emboss::FontFile> WxFontUtils::create_font_file(const wxFont &font)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return Emboss::load_font(font.GetHFONT());
|
||||
@ -246,11 +246,11 @@ bool WxFontUtils::set_italic(wxFont &font, std::shared_ptr<Emboss::FontFile>& fo
|
||||
wxFontStyle::wxFONTSTYLE_SLANT
|
||||
};
|
||||
if (font_file == nullptr)
|
||||
font_file = WxFontUtils::load_font(font);
|
||||
font_file = WxFontUtils::create_font_file(font);
|
||||
|
||||
for (wxFontStyle style : italic_styles) {
|
||||
font.SetStyle(style);
|
||||
std::unique_ptr<Emboss::FontFile> act_font_file = WxFontUtils::load_font(font);
|
||||
std::unique_ptr<Emboss::FontFile> act_font_file = WxFontUtils::create_font_file(font);
|
||||
if (act_font_file == nullptr) continue;
|
||||
|
||||
// is still same font file pointer?
|
||||
@ -272,11 +272,11 @@ bool WxFontUtils::set_bold(wxFont &font, std::shared_ptr<Emboss::FontFile>& font
|
||||
wxFontWeight::wxFONTWEIGHT_EXTRAHEAVY
|
||||
};
|
||||
if (font_file == nullptr)
|
||||
font_file = WxFontUtils::load_font(font);
|
||||
font_file = WxFontUtils::create_font_file(font);
|
||||
|
||||
for (wxFontWeight weight : bold_weight) {
|
||||
font.SetWeight(weight);
|
||||
std::unique_ptr<Emboss::FontFile> act_font_file = WxFontUtils::load_font(font);
|
||||
std::unique_ptr<Emboss::FontFile> act_font_file = WxFontUtils::create_font_file(font);
|
||||
if (act_font_file == nullptr) continue;
|
||||
if (font_file != nullptr)
|
||||
// is still same font?
|
||||
|
@ -20,7 +20,7 @@ public:
|
||||
static void *can_load(const wxFont &font);
|
||||
|
||||
// os specific load of wxFont
|
||||
static std::unique_ptr<Slic3r::Emboss::FontFile> load_font(const wxFont &font);
|
||||
static std::unique_ptr<Slic3r::Emboss::FontFile> create_font_file(const wxFont &font);
|
||||
|
||||
static FontItem::Type get_actual_type();
|
||||
static FontItem get_font_item(const wxFont &font);
|
||||
|
Loading…
x
Reference in New Issue
Block a user