Add editing of text volume

This commit is contained in:
Filip Sykala 2021-09-15 15:14:04 +02:00
parent 8226f74413
commit 8add695de9
7 changed files with 440 additions and 131 deletions

View file

@ -206,6 +206,7 @@ add_library(libslic3r STATIC
Technologies.hpp
Tesselate.cpp
Tesselate.hpp
TextConfiguration.hpp
TriangleMesh.cpp
TriangleMesh.hpp
TriangleMeshSlicer.cpp

View file

@ -10,18 +10,6 @@
using namespace Slic3r;
Emboss::FontItem::FontItem(const std::string &name, const std::string &path)
: name(name), path(path), type(Type::file_path)
{}
Emboss::FontItem::FontItem(const std::string &name, const std::string &path, Type type)
: name(name), path(path), type(type)
{}
Emboss::FontItem::FontItem(const std::wstring &name, const std::wstring &path)
: name(boost::nowide::narrow(name.c_str()))
, path(boost::nowide::narrow(path.c_str()))
, type(Type::file_path)
{}
// do not expose out of this file stbtt_ data types
class Privat
{
@ -30,6 +18,9 @@ public:
static std::optional<stbtt_fontinfo> load_font_info(const Emboss::Font &font);
static std::optional<Emboss::Glyph> get_glyph(stbtt_fontinfo &font_info, int unicode_letter, float flatness = 2.f);
static FontItem create_font_item(std::wstring name, std::wstring path);
};
std::optional<stbtt_fontinfo> Privat::load_font_info(const Emboss::Font &font)
@ -103,6 +94,11 @@ std::optional<Emboss::Glyph> Privat::get_glyph(stbtt_fontinfo &font_info, int un
return glyph;
}
FontItem Privat::create_font_item(std::wstring name, std::wstring path) {
return FontItem(boost::nowide::narrow(name.c_str()),
boost::nowide::narrow(path.c_str()));
}
#ifdef _WIN32
#include <windows.h>
#include <wingdi.h>
@ -238,15 +234,14 @@ void get_OS_font()
}
Emboss::FontList Emboss::get_font_list()
FontList Emboss::get_font_list()
{
//auto a = get_font_path(L"none");
get_OS_font();
//get_OS_font();
//choose_font_dlg();
//FontList list1 = get_font_list_by_enumeration();
//FontList list2 = get_font_list_by_register();
//FontList list3 = get_font_list_by_folder();
//FontList list3 = get_font_list_by_folder();
return get_font_list_by_register();
}
@ -260,7 +255,7 @@ bool exists_file(const std::wstring &name)
}
}
Emboss::FontList Emboss::get_font_list_by_register() {
FontList Emboss::get_font_list_by_register() {
static const LPWSTR fontRegistryPath = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts";
HKEY hKey;
LONG result;
@ -310,7 +305,7 @@ Emboss::FontList Emboss::get_font_list_by_register() {
if (pos >= font_name_w.size()) continue;
// remove TrueType text from name
font_name_w = std::wstring(font_name_w, 0, pos);
font_list.emplace_back(font_name_w, path_w);
font_list.emplace_back(Privat::create_font_item(font_name_w, path_w));
} while (result != ERROR_NO_MORE_ITEMS);
delete[] font_name;
delete[] fileTTF_name;
@ -336,7 +331,7 @@ bool CALLBACK EnumFamCallBack(LPLOGFONT lplf,
UNREFERENCED_PARAMETER(lpntm);
}
Emboss::FontList Emboss::get_font_list_by_enumeration() {
FontList Emboss::get_font_list_by_enumeration() {
HDC hDC = GetDC(NULL);
std::vector<std::wstring> font_names;
@ -345,12 +340,12 @@ Emboss::FontList Emboss::get_font_list_by_enumeration() {
FontList font_list;
for (const std::wstring &font_name : font_names) {
font_list.emplace_back(font_name, L"");
font_list.emplace_back(Privat::create_font_item(font_name, L""));
}
return font_list;
}
Emboss::FontList Emboss::get_font_list_by_folder() {
FontList Emboss::get_font_list_by_folder() {
FontList result;
WCHAR winDir[MAX_PATH];
UINT winDir_size = GetWindowsDirectory(winDir, MAX_PATH);
@ -367,7 +362,7 @@ Emboss::FontList Emboss::get_font_list_by_folder() {
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue;
std::wstring file_name(fd.cFileName);
// TODO: find font name instead of filename
result.emplace_back(file_name, search_dir + file_name);
result.emplace_back(Privat::create_font_item(file_name, search_dir + file_name));
} while (::FindNextFile(hFind, &fd));
::FindClose(hFind);
}

View file

@ -7,6 +7,7 @@
#include <memory>
#include <admesh/stl.h> // indexed_triangle_set
#include "Polygon.hpp"
#include "TextConfiguration.hpp"
namespace Slic3r {
@ -19,28 +20,10 @@ class Emboss
public:
Emboss() = delete;
struct FontItem
{
std::string name;
std::string path;
enum class Type;
Type type;
FontItem(const std::string &name, const std::string &path);
FontItem(const std::string &name, const std::string &path, Type type);
FontItem(const std::wstring &name, const std::wstring &path);
// way of load font described in path string
enum class Type {
file_path, // path is file loacation on computer - no move between computers
wx_font_descr // path is font descriptor generated by wxWidgets - limits for os/language move
};
};
using FontList = std::vector<FontItem>;
/// <summary>
/// Collect fonts registred inside OS
/// </summary>
/// <returns>OS resistred TTF font files(full path) with names</returns>
/// <returns>OS registred TTF font files(full path) with names</returns>
static FontList get_font_list();
#ifdef _WIN32
static FontList get_font_list_by_register();
@ -55,24 +38,6 @@ public:
/// <returns>File path to font when found</returns>
static std::optional<std::wstring> get_font_path(const std::wstring &font_face_name);
// user defined font property
struct FontProp
{
// define extra space between letters, negative mean closer letter
int char_gap = 0;
// define extra space between lines, negative mean closer lines
int line_gap = 0;
// Precision of lettter outline curve in conversion to lines
float flatness = 2.0;
// Height of letter [in mm]
float size_in_mm = 10;
// Z depth of text [in mm]
float emboss = 5;
// TODO: add enum class Align: center/left/right
FontProp() = default;
};
// description of one letter
struct Glyph
{
@ -185,7 +150,7 @@ public:
return std::make_pair(res.first * m_scale, res.second * m_scale);
}
float m_scale;
float m_scale;
};
};

View file

@ -14,12 +14,14 @@
#include "Arrange.hpp"
#include "CustomGCode.hpp"
#include "enum_bitmask.hpp"
#include "TextConfiguration.hpp"
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include <optional>
namespace cereal {
class BinaryInputArchive;
@ -636,6 +638,10 @@ public:
// List of mesh facets painted for MMU segmentation.
FacetsAnnotation mmu_segmentation_facets;
// Is set only when volume is Embossed Text type
// Contain information how to re-create volume
std::optional<TextConfiguration> text_configuration;
// A parent object owning this modifier volume.
ModelObject* get_object() const { return this->object; }
ModelVolumeType type() const { return m_type; }

View file

@ -0,0 +1,70 @@
#ifndef slic3r_TextConfiguration_hpp_
#define slic3r_TextConfiguration_hpp_
#include <vector>
#include <string>
namespace Slic3r {
// represent selected font
// Name must be human readable is visible in gui
// (Path + Type) must define how to open font for using on different OS
struct FontItem
{
std::string name;
std::string path;
enum class Type;
Type type;
FontItem() : type(Type::undefined) {}
FontItem(const std::string &name, const std::string &path, Type type = Type::file_path)
: name(name), path(path), type(type)
{}
// way of load font described in path string
enum class Type {
undefined = 0,
file_path, // path is file loacation on computer - no move between computers
wx_font_descr, // path is font descriptor generated by wxWidgets - limits for os/language move
};
};
using FontList = std::vector<FontItem>;
// user defined font property
struct FontProp
{
// define extra space between letters, negative mean closer letter
int char_gap = 0;
// define extra space between lines, negative mean closer lines
int line_gap = 0;
// Precision of lettter outline curve in conversion to lines
float flatness = 2.0;
// Height of letter [in mm]
float size_in_mm = 10;
// Z depth of text [in mm]
float emboss = 5;
// TODO: add enum class Align: center/left/right
FontProp() = default;
};
// define how to create 'Text volume'
struct TextConfiguration
{
// define font
FontItem font_item;
// user modification of font
FontProp font_prop;
std::string text;
TextConfiguration() = default;
TextConfiguration(const FontItem & font_item,
const FontProp & font_prop,
const std::string &text)
: font_item(font_item), font_prop(font_prop), text(text)
{}
};
} // namespace Slic3r
#endif // slic3r_TextConfiguration_hpp_

View file

@ -8,6 +8,8 @@
#include "libslic3r/Model.hpp"
#include "nanosvg/nanosvg.h" // load SVG file
#include <wx/font.h>
#include <wx/fontdlg.h>
@ -21,13 +23,12 @@ public:
// os specific load of wxFont
static std::optional<Slic3r::Emboss::Font> load_font(const wxFont &font);
// Must be in gui because of wxWidget
static std::optional<Slic3r::Emboss::Font> load_font(const Emboss::FontItem &fi);
static std::optional<Slic3r::Emboss::Font> load_font(const FontItem &fi);
static Slic3r::Emboss::FontItem get_font_item(const wxFont &font);
static FontItem get_font_item(const wxFont &font);
// load font used by Operating system as default GUI
static Slic3r::Emboss::FontItem get_os_font();
static FontItem get_os_font();
static std::string get_human_readable_name(const wxFont &font);
// serialize / deserialize font
@ -52,23 +53,20 @@ GLGizmoEmboss::GLGizmoEmboss(GLCanvas3D &parent)
{
// TODO: suggest to use https://fontawesome.com/
// (copy & paste) unicode symbols from web
bool is_font_loaded = load_font();
add_fonts(Emboss::get_font_list());
add_fonts({WxFontUtils::get_os_font()});
if (!is_font_loaded) {
bool is_font_loaded = load_font();
FontList fl = Emboss::get_font_list();
m_font_list.insert(m_font_list.end(), fl.begin(), fl.end());
m_font_list.emplace_back(WxFontUtils::get_os_font());
while (!is_font_loaded && !m_font_list.empty()) {
// can't load so erase it from list
m_font_list.erase(m_font_list.begin() + m_font_selected);
m_font_selected = 0; // select first
do{
is_font_loaded = load_font();
if (!is_font_loaded) m_font_list.erase(m_font_list.begin());
} while (!is_font_loaded && !m_font_list.empty());
m_font_selected = 0; // select first
is_font_loaded = load_font();
}
int index = 0;
for (char &c : _u8L("Embossed text")) { m_text[index++] = c; }
m_text[index] = '\0';
sort_fonts();
set_default_configuration();
}
GLGizmoEmboss::~GLGizmoEmboss() {}
@ -88,50 +86,156 @@ std::string GLGizmoEmboss::on_get_name() const
void GLGizmoEmboss::on_render() {}
void GLGizmoEmboss::on_render_for_picking() {}
// took from nanosvgrast.h function nsvgRasterize->nsvg__flattenShape
void flatten_cubic_bez(Slic3r::Polygon &polygon,
float tessTol,
float x1,
float y1,
float x2,
float y2,
float x3,
float y3,
float x4,
float y4,
int level)
{
float x12, y12, x23, y23, x34, y34, x123, y123, x234, y234, x1234,
y1234;
float dx, dy, d2, d3;
if (level == 0) return;
x12 = (x1 + x2) * 0.5f;
y12 = (y1 + y2) * 0.5f;
x23 = (x2 + x3) * 0.5f;
y23 = (y2 + y3) * 0.5f;
x34 = (x3 + x4) * 0.5f;
y34 = (y3 + y4) * 0.5f;
x123 = (x12 + x23) * 0.5f;
y123 = (y12 + y23) * 0.5f;
dx = x4 - x1;
dy = y4 - y1;
d2 = std::abs(((x2 - x4) * dy - (y2 - y4) * dx));
d3 = std::abs(((x3 - x4) * dy - (y3 - y4) * dx));
if ((d2 + d3) * (d2 + d3) < tessTol * (dx * dx + dy * dy)) {
polygon.points.emplace_back(x4, y4);
return;
}
--level;
if (level == 0) return;
x234 = (x23 + x34) * 0.5f;
y234 = (y23 + y34) * 0.5f;
x1234 = (x123 + x234) * 0.5f;
y1234 = (y123 + y234) * 0.5f;
flatten_cubic_bez(polygon, tessTol, x1, y1, x12, y12, x123, y123, x1234, y1234, level);
flatten_cubic_bez(polygon, tessTol, x1234, y1234, x234, y234, x34, y34, x4, y4, level);
}
Slic3r::ExPolygons to_ExPolygons(NSVGimage *image,
float tessTol = 10.,
int max_level = 10)
{
Polygons polygons;
for (NSVGshape *shape = image->shapes; shape != NULL;
shape = shape->next) {
if (!(shape->flags & NSVG_FLAGS_VISIBLE)) continue;
Slic3r::Polygon polygon;
if (shape->fill.type != NSVG_PAINT_NONE) {
for (NSVGpath *path = shape->paths; path != NULL;
path = path->next) {
// Flatten path
polygon.points.emplace_back(path->pts[0], path->pts[1]);
for (size_t i = 0; i < path->npts - 1; i += 3) {
float *p = &path->pts[i * 2];
flatten_cubic_bez(polygon, tessTol, p[0], p[1], p[2],
p[3], p[4], p[5], p[6], p[7],
max_level);
}
if (path->closed) {
polygons.push_back(polygon);
polygon = Slic3r::Polygon();
}
}
}
polygons.push_back(polygon);
}
return union_ex(polygons);
}
#include "libslic3r/SVG.hpp"
void GLGizmoEmboss::on_render_input_window(float x, float y, float bottom_limit)
{
if (!m_gui_cfg.has_value()) m_gui_cfg.emplace(GuiCfg());
check_selection();
int flag = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize |
ImGuiWindowFlags_NoCollapse;
m_imgui->begin(on_get_name(), flag);
if (!m_font.has_value()) {
ImGui::Text("Warning: No font is selected. Select correct one.");
}
draw_font_list();
static std::string fontName;
if (ImGui::Button(_L("choose font").c_str())) {
static wxFontData data; // keep last selected font
wxFontDialog font_dialog((wxWindow*)wxGetApp().mainframe, data);
font_dialog.SetTitle(_L("Select font for Emboss"));
if (font_dialog.ShowModal() == wxID_OK) {
data = font_dialog.GetFontData();
wxFont font = data.GetChosenFont();
auto fontOpt = WxFontUtils::load_font(font);
if (fontOpt.has_value()) {
Emboss::FontItem fontItem = WxFontUtils::get_font_item(font);
m_font_selected = m_font_list.size();
add_fonts({fontItem});
m_font = fontOpt;
process();
}
}
choose_font_by_dialog();
}
ImGui::SameLine();
if (ImGui::Button(_L("use system font").c_str())) {
wxSystemSettings ss;
wxFont f = ss.GetFont(wxSYS_DEFAULT_GUI_FONT);
size_t font_index = m_font_list.size();
FontItem fi = WxFontUtils::get_font_item(f);
m_font_list.emplace_back(fi);
bool loaded = load_font(font_index);
}
if (!fontName.empty()) ImGui::Text(fontName.c_str());
ImGui::SameLine();
draw_add_button();
ImGui::InputFloat("Size[in mm]", &m_font_prop.size_in_mm);
ImGui::InputFloat("Emboss[in mm]", &m_font_prop.emboss);
if (ImGui::InputFloat("Flatness", &m_font_prop.flatness))
if(m_font.has_value()) m_font->cache.clear();
ImGui::InputInt("CharGap[in font points]", &m_font_prop.char_gap);
ImGui::InputInt("LineGap[in font points]", &m_font_prop.line_gap);
ImGui::InputFloat3("Origin", m_orientation.origin.data());
if (ImGui::Button("add svg")) {
std::string filePath =
"C:/Users/filip/Downloads/fontawesome-free-5.15.4-web/"
"fontawesome-free-5.15.4-web/svgs/solid/bicycle.svg";
NSVGimage *image = nsvgParseFromFile(filePath.c_str(), "mm", 96.0f);
ExPolygons polys = to_ExPolygons(image);
for (auto &poly : polys) poly.scale(1e5);
SVG svg("converted.svg", BoundingBox(polys.front().contour.points));
svg.draw(polys);
nsvgDelete(image);
}
if (ImGui::InputFloat("Size[in mm]", &m_font_prop.size_in_mm)) {
if (m_font_prop.size_in_mm < 0.1) m_font_prop.size_in_mm = 10;
process();
}
if (ImGui::InputFloat("Emboss[in mm]", &m_font_prop.emboss)) process();
if (ImGui::InputFloat("Flatness", &m_font_prop.flatness)) {
if (m_font.has_value()) m_font->cache.clear();
process();
}
if (ImGui::InputInt("CharGap[in font points]", &m_font_prop.char_gap)) process();
if (ImGui::InputInt("LineGap[in font points]", &m_font_prop.line_gap)) process();
//ImGui::InputFloat3("Origin", m_orientation.origin.data());
//if (ImGui::InputFloat3("Normal", m_normal.data())) m_normal.normalize();
//if (ImGui::InputFloat3("Up", m_up.data())) m_up.normalize();
m_imgui->disabled_begin(!m_font.has_value());
if (ImGui::Button("Preview")) process();
// create default text
if (m_volume == nullptr) {
if (ImGui::Button("Generate preview")) process();
}
m_imgui->disabled_end();
ImVec2 input_size(-FLT_MIN, ImGui::GetTextLineHeight() * 6);
ImGuiInputTextFlags flags =
@ -149,17 +253,7 @@ void GLGizmoEmboss::on_render_input_window(float x, float y, float bottom_limit)
// change text size
int max_text_size = static_cast<int>(m_text_size);
if (ImGui::InputInt("max text size", &max_text_size, 8, 64)) {
if (max_text_size < 4) max_text_size = 4;
std::unique_ptr<char[]> newData(new char[max_text_size]);
size_t index = 0;
while ((index+1) < max_text_size) {
if (m_text.get()[index] == '\0') break;
newData.get()[index] = m_text.get()[index];
++index;
}
newData.get()[index] = '\0';
m_text = std::move(newData);
m_text_size = max_text_size;
set_max_text_size(static_cast<size_t>(max_text_size));
}
// draw 2d triangle in IMGUI
@ -172,7 +266,6 @@ void GLGizmoEmboss::on_render_input_window(float x, float y, float bottom_limit)
m_imgui->end();
}
bool GLGizmoEmboss::on_is_activable() const
{
return !m_parent.get_selection().is_empty();
@ -195,8 +288,10 @@ void GLGizmoEmboss::on_set_state()
}
m_volume = nullptr;
} else if (GLGizmoBase::m_state == GLGizmoBase::On) {
if(!set_volume()) set_default_configuration();
// when open by hyperlink it needs to show up
//request_rerender();
m_parent.reload_scene(true);
}
}
@ -263,6 +358,63 @@ bool GLGizmoEmboss::gizmo_event(SLAGizmoEventType action,
return false;
}
void GLGizmoEmboss::set_default_configuration() {
set_text(_u8L("Embossed text"));
m_font_prop = FontProp();
// may be set default font?
}
void GLGizmoEmboss::check_selection()
{
// is text created?
if (m_volume == nullptr) return;
ModelVolume* vol = get_selected_volume();
// is same volume selected?
if (m_volume == vol) return;
// Do not use actual edited value when switch volume
ImGui::SetKeyboardFocusHere(-1);
// is selected volume embossed?
if (vol!= nullptr && vol->text_configuration.has_value()) {
m_volume = vol;
load_configuration(*vol->text_configuration);
return;
}
// behave like adding new text
m_volume == nullptr;
}
ModelVolume *GLGizmoEmboss::get_selected_volume()
{
return get_selected_volume(m_parent.get_selection(),
wxGetApp().plater()->model().objects);
}
ModelVolume *GLGizmoEmboss::get_selected_volume(const Selection &selection,
const ModelObjectPtrs objects)
{
int object_idx = selection.get_object_idx();
// is more object selected?
if (object_idx == -1) return nullptr;
auto volume_idxs = selection.get_volume_idxs();
// is more volumes selected?
if (volume_idxs.size() != 1) return nullptr;
unsigned int vol_id_gl = *volume_idxs.begin();
const GLVolume * vol_gl = selection.get_volume(vol_id_gl);
const GLVolume::CompositeID &id = vol_gl->composite_id;
if (id.object_id >= objects.size()) return nullptr;
ModelObject *object = objects[id.object_id];
if (id.volume_id >= object->volumes.size()) return nullptr;
return object->volumes[id.volume_id];
}
// create_text_volume()
void GLGizmoEmboss::process() {
if (!m_font.has_value()) return;
@ -305,6 +457,7 @@ void GLGizmoEmboss::process() {
// set a default extruder value, since user can't add it manually
m_volume->config.set_key_value("extruder", new ConfigOptionInt(0));
m_volume->text_configuration = create_configuration();
// select new added volume
ModelVolume *new_volume = m_volume;
@ -343,7 +496,7 @@ void GLGizmoEmboss::draw_add_button() {
if (dialog.ShowModal() == wxID_OK) dialog.GetPaths(input_files);
if (input_files.IsEmpty()) return;
Emboss::FontList font_list;
FontList font_list;
font_list.reserve(input_files.size());
for (auto &input_file : input_files) {
std::string path = std::string(input_file.c_str());
@ -368,7 +521,7 @@ void GLGizmoEmboss::draw_font_list()
{
auto &current = m_font_list[m_font_selected];
if (ImGui::BeginCombo("##font_selector", current.name.c_str())) {
for (const Emboss::FontItem &f : m_font_list) {
for (const FontItem &f : m_font_list) {
ImGui::PushID((void *) &f.name);
std::string name =
(f.name.size() < m_gui_cfg->max_font_name) ?
@ -411,6 +564,14 @@ void GLGizmoEmboss::draw_font_list()
}
}
bool GLGizmoEmboss::load_font(size_t font_index)
{
std::swap(font_index, m_font_selected);
bool is_loaded = load_font();
if (!is_loaded) std::swap(font_index, m_font_selected);
return is_loaded;
}
bool GLGizmoEmboss::load_font() {
if (m_font_selected >= m_font_list.size()) return false;
auto font = WxFontUtils::load_font(m_font_list[m_font_selected]);
@ -419,18 +580,62 @@ bool GLGizmoEmboss::load_font() {
return true;
}
std::optional<Emboss::Font> WxFontUtils::load_font(const Emboss::FontItem &fi)
void GLGizmoEmboss::set_text(const std::string &text) {
if (text.size() > m_text_size-1)
set_max_text_size(text.size() + 1);
int index = 0;
for (const char &c : text) m_text[index++] = c;
m_text[index] = '\0';
}
void GLGizmoEmboss::set_max_text_size(size_t size) {
if (size < 4) size = 4;
std::unique_ptr<char[]> newData(new char[size]);
size_t index = 0;
while ((index + 1) < size) {
if (m_text.get()[index] == '\0') break;
newData.get()[index] = m_text.get()[index];
++index;
}
newData.get()[index] = '\0';
m_text = std::move(newData);
m_text_size = size;
}
bool GLGizmoEmboss::choose_font_by_dialog() {
// keep last selected font did not work
// static wxFontData data;
// wxFontDialog font_dialog((wxWindow *) wxGetApp().mainframe, data);
wxFontDialog font_dialog(nullptr);
font_dialog.SetTitle(_L("Select font for Emboss"));
if (font_dialog.ShowModal() != wxID_OK) return false;
wxFontData data = font_dialog.GetFontData();
wxFont font = data.GetChosenFont();
size_t font_index = m_font_list.size();
m_font_list.emplace_back(WxFontUtils::get_font_item(font));
if (!load_font(font_index)) {
m_font_list.pop_back();
return false;
}
sort_fonts();
process();
return true;
}
std::optional<Emboss::Font> WxFontUtils::load_font(const FontItem &fi)
{
switch (fi.type) {
case Emboss::FontItem::Type::file_path:
case FontItem::Type::file_path:
return Emboss::load_font(fi.path.c_str());
case Emboss::FontItem::Type::wx_font_descr:
case FontItem::Type::wx_font_descr:
return WxFontUtils::load_font(WxFontUtils::load_wxFont(fi.path));
}
return {};
}
std::optional<Slic3r::Emboss::Font> WxFontUtils::load_font(const wxFont &font)
std::optional<Emboss::Font> WxFontUtils::load_font(const wxFont &font)
{
if (!font.IsOk()) return {};
#ifdef _WIN32
@ -448,18 +653,18 @@ std::optional<Slic3r::Emboss::Font> WxFontUtils::load_font(const wxFont &font)
#endif
}
Slic3r::Emboss::FontItem WxFontUtils::get_font_item(const wxFont &font)
FontItem WxFontUtils::get_font_item(const wxFont &font)
{
std::string name = get_human_readable_name(font);
std::string fontDesc = store_wxFont(font);
return Emboss::FontItem(name, fontDesc, Emboss::FontItem::Type::wx_font_descr);
return FontItem(name, fontDesc, FontItem::Type::wx_font_descr);
}
Slic3r::Emboss::FontItem WxFontUtils::get_os_font()
FontItem WxFontUtils::get_os_font()
{
wxSystemSettings ss;
wxFont ss_font = ss.GetFont(wxSYS_ANSI_VAR_FONT);
Emboss::FontItem fi = get_font_item(ss_font);
FontItem fi = get_font_item(ss_font);
fi.name += +" (" + _u8L("OS default") + ")";
return get_font_item(ss_font);
}
@ -502,7 +707,7 @@ void GLGizmoEmboss::sort_fonts() {
return m_font_list[i1].name < m_font_list[i2].name;
});
Emboss::FontList font_list;
FontList font_list;
font_list.reserve(m_font_list.size());
size_t selected = 0;
for (const size_t &i : idx) {
@ -513,18 +718,68 @@ void GLGizmoEmboss::sort_fonts() {
m_font_selected = selected;
}
void GLGizmoEmboss::add_fonts(const Emboss::FontList &font_list) {
void GLGizmoEmboss::add_fonts(const FontList &font_list) {
m_font_list.insert(m_font_list.end(), font_list.begin(), font_list.end());
sort_fonts();
}
bool GLGizmoEmboss::set_volume()
{
ModelVolume *vol = get_selected_volume();
// Is selected only one volume
if (vol == nullptr) return false;
// Is volume created by Emboss?
if (!vol->text_configuration.has_value()) return false;
// set selected volume
m_volume = vol;
load_configuration(*vol->text_configuration);
return true;
}
TextConfiguration GLGizmoEmboss::create_configuration() {
std::string text((const char *) m_text.get());
return TextConfiguration(m_font_list[m_font_selected], m_font_prop, text);
}
bool GLGizmoEmboss::load_configuration(const TextConfiguration &configuration)
{
size_t index = m_font_list.size();
for (const auto &font_item : m_font_list) {
if (font_item.type == configuration.font_item.type &&
font_item.path == configuration.font_item.path) {
index = &font_item - &m_font_list.front();
}
}
size_t prev_font_selected = m_font_selected;
// when not in font list add to list
if (index >= m_font_list.size()) {
m_font_selected = m_font_list.size();
add_fonts({configuration.font_item});
} else {
m_font_selected = index;
}
// When can't load font
if (!load_font()) {
// remove bad loadabled font, for correct prev index
m_font_list.erase(m_font_list.begin() + m_font_selected);
m_font_selected = prev_font_selected;
return false;
}
m_font_prop = configuration.font_prop;
set_text(configuration.text);
return true;
}
std::string GLGizmoEmboss::create_volume_name()
{
size_t max_len = 20;
std::string text((const char *)m_text.get());
if (text.size() > max_len)
text = text.substr(0, max_len - 3) + " ..";
return _u8L("Text") + ": " + text;
return _u8L("Text") + " - " + text;
}
// any existing icon filename to not influence GUI

View file

@ -37,14 +37,31 @@ protected:
virtual void on_set_state() override;
private:
void set_default_configuration();
void check_selection();
// more general function --> move to select
ModelVolume *get_selected_volume();
static ModelVolume *get_selected_volume(const Selection &selection, const ModelObjectPtrs objects);
void process();
void close();
void draw_font_list();
void draw_add_button();
bool load_font();
// try to set font_index
bool load_font(size_t font_index);
void set_text(const std::string &text);
void set_max_text_size(size_t size);
bool choose_font_by_dialog();
void sort_fonts();
void add_fonts(const Emboss::FontList &font_list);
void add_fonts(const FontList &font_list);
bool set_volume();
// Create object described how to make a Volume
TextConfiguration create_configuration();
bool load_configuration(const TextConfiguration& configuration);
std::string create_volume_name();
@ -58,15 +75,15 @@ private:
};
std::optional<GuiCfg> m_gui_cfg;
Emboss::FontList m_font_list;
size_t m_font_selected;// index to m_font_list
FontList m_font_list;
size_t m_font_selected;// index to m_font_list
std::optional<Emboss::Font> m_font;
size_t m_text_size;
std::unique_ptr<char[]> m_text;
Emboss::FontProp m_font_prop;
FontProp m_font_prop;
// text position
struct Orientation