Choose font by wxWidgetDialog

This commit is contained in:
Filip Sykala 2021-09-09 19:36:51 +02:00
parent 578abe4cce
commit 9d52ceee44
6 changed files with 317 additions and 109 deletions

View file

@ -25,13 +25,7 @@ public:
Privat() = delete;
static std::optional<stbtt_fontinfo> load_font_info(const Emboss::Font &font);
struct Glyph
{
Polygons polygons;
int advance_width, left_side_bearing;
};
static std::optional<Glyph> get_glyph(stbtt_fontinfo &font_info, int unicode_letter, float flatness = 2.f);
static std::optional<Emboss::Glyph> get_glyph(stbtt_fontinfo &font_info, int unicode_letter, float flatness = 2.f);
};
std::optional<stbtt_fontinfo> Privat::load_font_info(const Emboss::Font &font)
@ -49,7 +43,7 @@ std::optional<stbtt_fontinfo> Privat::load_font_info(const Emboss::Font &font)
return font_info;
}
std::optional<Privat::Glyph> Privat::get_glyph(stbtt_fontinfo &font_info, int unicode_letter, float flatness)
std::optional<Emboss::Glyph> Privat::get_glyph(stbtt_fontinfo &font_info, int unicode_letter, float flatness)
{
int glyph_index = stbtt_FindGlyphIndex(&font_info, unicode_letter);
if (glyph_index == 0) {
@ -58,7 +52,7 @@ std::optional<Privat::Glyph> Privat::get_glyph(stbtt_fontinfo &font_info, int un
return {};
}
Privat::Glyph glyph;
Emboss::Glyph glyph;
stbtt_GetGlyphHMetrics(&font_info, glyph_index, &glyph.advance_width, &glyph.left_side_bearing);
stbtt_vertex *vertices;
@ -96,16 +90,15 @@ std::optional<Privat::Glyph> Privat::get_glyph(stbtt_fontinfo &font_info, int un
// change outer cw to ccw and inner ccw to cw order
std::reverse(pts.begin(), pts.end());
glyph.polygons.emplace_back(pts);
}
// fix for bad defined fonts
glyph.polygons = union_(glyph.polygons);
// inner cw - hole
// outer ccw - contour
return glyph;
}
#ifdef _WIN32
#include <windows.h>
#include <wingdi.h>
@ -210,23 +203,46 @@ void choose_font_dlg() {
void get_OS_font()
{
HGDIOBJ g_hfFont = GetStockObject(DEFAULT_GUI_FONT);
LOGFONT lf;
HGDIOBJ g_hfFont = GetStockObject(DEFAULT_GUI_FONT);
GetObject(g_hfFont, sizeof(LOGFONT), &lf);
std::wcout << "Default WIN font is " << (std::wstring) lf.lfFaceName
<< std::endl;
std::wcout << "DEFAULT_GUI_FONT is " << (std::wstring) lf.lfFaceName << std::endl;
g_hfFont = GetStockObject(OEM_FIXED_FONT);
GetObject(g_hfFont, sizeof(LOGFONT), &lf);
std::wcout << "OEM_FIXED_FONT is " << (std::wstring) lf.lfFaceName << std::endl;
g_hfFont = GetStockObject(ANSI_FIXED_FONT);
GetObject(g_hfFont, sizeof(LOGFONT), &lf);
std::wcout << "ANSI_FIXED_FONT is " << (std::wstring) lf.lfFaceName << std::endl;
g_hfFont = GetStockObject(ANSI_VAR_FONT);
GetObject(g_hfFont, sizeof(LOGFONT), &lf);
std::wcout << "ANSI_VAR_FONT is " << (std::wstring) lf.lfFaceName << std::endl;
g_hfFont = GetStockObject(SYSTEM_FONT);
GetObject(g_hfFont, sizeof(LOGFONT), &lf);
std::wcout << "SYSTEM_FONT is " << (std::wstring) lf.lfFaceName << std::endl;
g_hfFont = GetStockObject(DEVICE_DEFAULT_FONT);
GetObject(g_hfFont, sizeof(LOGFONT), &lf);
std::wcout << "DEVICE_DEFAULT_FONT is " << (std::wstring) lf.lfFaceName << std::endl;
g_hfFont = GetStockObject(SYSTEM_FIXED_FONT);
GetObject(g_hfFont, sizeof(LOGFONT), &lf);
std::wcout << "SYSTEM_FIXED_FONT is " << (std::wstring) lf.lfFaceName << std::endl;
}
//#include <wx/fontdlg.h>
Emboss::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();
}
@ -337,9 +353,11 @@ Emboss::FontList Emboss::get_font_list_by_folder() {
std::wstring search_dir = std::wstring(winDir, winDir_size) + L"\\Fonts\\";
WIN32_FIND_DATA fd;
HANDLE hFind;
auto iterate_files = [&hFind, &fd, &search_dir, &result]() {
if (hFind == INVALID_HANDLE_VALUE) return;
// read all (real) files in current folder
// By https://en.wikipedia.org/wiki/TrueType has also suffix .tte
std::vector<std::wstring> suffixes = {L"*.ttf", L"*.ttc", L"*.tte"};
for (const std::wstring &suffix : suffixes) {
hFind = ::FindFirstFile((search_dir + suffix).c_str(), &fd);
if (hFind == INVALID_HANDLE_VALUE) continue;
do {
// skip folder . and ..
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue;
@ -347,13 +365,8 @@ Emboss::FontList Emboss::get_font_list_by_folder() {
// TODO: find font name instead of filename
result.emplace_back(file_name, search_dir + file_name);
} while (::FindNextFile(hFind, &fd));
::FindClose(hFind);
};
hFind = ::FindFirstFile((search_dir + L"*.ttf").c_str(), &fd);
iterate_files();
hFind = ::FindFirstFile((search_dir + L"*.ttc").c_str(), &fd);
iterate_files();
::FindClose(hFind);
}
return result;
}
@ -366,6 +379,34 @@ std::optional<std::wstring> Emboss::get_font_path(const std::wstring &font_face_
}
#endif
std::optional<Emboss::Font> Emboss::load_font(std::vector<unsigned char> data)
{
Font res;
res.buffer = std::move(data);
unsigned int index = 0;
int font_offset = 0;
while (font_offset >= 0) {
font_offset = stbtt_GetFontOffsetForIndex(res.buffer.data(), index++);
}
// at least one font must be inside collection
if (index < 1) {
std::cerr << "There is no font collection inside file.";
return {};
}
// select default font on index 0
res.index = 0;
res.count = index;
auto font_info = Privat::load_font_info(res);
if (!font_info.has_value()) return {};
// load information about line gap
stbtt_GetFontVMetrics(&(*font_info), &res.ascent, &res.descent,
&res.linegap);
return res;
}
std::optional<Emboss::Font> Emboss::load_font(const char *file_path)
{
FILE *file = fopen(file_path, "rb");
@ -386,52 +427,63 @@ std::optional<Emboss::Font> Emboss::load_font(const char *file_path)
}
rewind(file);
Font res;
res.buffer = std::vector<unsigned char>(size);
size_t count_loaded_bytes = fread((void *) &res.buffer.front(), 1, size, file);
unsigned int index = 0;
int font_offset = 0;
while (font_offset >= 0) {
font_offset = stbtt_GetFontOffsetForIndex(res.buffer.data(), index++);
std::vector<unsigned char> buffer(size);
size_t count_loaded_bytes = fread((void *) &buffer.front(), 1, size, file);
if (count_loaded_bytes != size) {
std::cerr << "Different loaded(from file) data size.";
return {};
}
// at least one font must be inside collection
if (index < 1) {
std::cerr << "There is no font collection inside file.";
return {};
}
// select default font on index 0
res.index = 0;
res.count = index;
auto font_info = Privat::load_font_info(res);
if (!font_info.has_value()) return {};
// load information about line gap
stbtt_GetFontVMetrics(&(*font_info), &res.ascent, &res.descent, &res.linegap);
return res;
return load_font(std::move(buffer));
}
Polygons Emboss::letter2polygons(const Font &font, char letter, float flatness)
#ifdef _WIN32
std::optional<Emboss::Font> Emboss::load_font(HFONT hfont)
{
HDC hdc = ::CreateCompatibleDC(NULL);
if (hdc == NULL) {
std::cerr << "Can't create HDC by CreateCompatibleDC(NULL).";
return {};
}
::SelectObject(hdc, hfont);
size_t size = ::GetFontData(hdc, 0, 0, NULL, 0);
if (size == 0) {
std::cerr << "HFONT doesn't have size.";
::DeleteDC(hdc);
return {};
}
std::vector<unsigned char> buffer(size);
size_t loaded_size = ::GetFontData(hdc, 0, 0, buffer.data(), size);
::DeleteDC(hdc);
if (size != loaded_size) {
std::cerr << "Different loaded(from HFONT) data size.";
return {};
}
return load_font(std::move(buffer));
}
#endif // _WIN32
std::optional<Emboss::Glyph> Emboss::letter2glyph(const Font &font,
int letter,
float flatness)
{
auto font_info_opt = Privat::load_font_info(font);
if (!font_info_opt.has_value()) return Polygons();
if (!font_info_opt.has_value()) return {};
stbtt_fontinfo *font_info = &(*font_info_opt);
auto glyph_opt = Privat::get_glyph(*font_info_opt, (int) letter, flatness);
if (!glyph_opt.has_value()) return Polygons();
return union_(glyph_opt->polygons);
return Privat::get_glyph(*font_info_opt, (int) letter, flatness);
}
Polygons Emboss::text2polygons(const Font & font,
const char * text,
const FontProp &font_prop)
const FontProp &font_prop,
Glyphs & cache)
{
auto font_info_opt = Privat::load_font_info(font);
if (!font_info_opt.has_value()) return Polygons();
stbtt_fontinfo *font_info = &(*font_info_opt);
std::optional<stbtt_fontinfo> font_info_opt;
Point cursor(0, 0);
Polygons result;
@ -443,16 +495,27 @@ Polygons Emboss::text2polygons(const Font & font,
continue;
}
int unicode = static_cast<int>(wc);
auto glyph_opt = Privat::get_glyph(*font_info_opt, unicode, font_prop.flatness);
if (!glyph_opt.has_value()) continue;
std::optional<Glyph> glyph_opt;
auto glyph_item = cache.find(unicode);
if (glyph_item != cache.end()) glyph_opt = glyph_item->second;
else {
if (!font_info_opt.has_value()) {
font_info_opt = Privat::load_font_info(font);
// can load font info?
if (!font_info_opt.has_value()) return Polygons();
}
glyph_opt = Privat::get_glyph(*font_info_opt, unicode,
font_prop.flatness);
// has definition inside of font?
if (!glyph_opt.has_value()) continue;
cache[unicode] = *glyph_opt;
}
// move glyph to cursor position
Polygons polygons = glyph_opt->polygons; // copy
for (Polygon &polygon : polygons)
for (Point &p : polygon.points) p += cursor;
polygon.translate(cursor);
cursor.x() += glyph_opt->advance_width + font_prop.char_gap;
polygons_append(result, polygons);
}
return union_(result);

View file

@ -75,30 +75,49 @@ public:
FontProp() = default;
};
// description of one letter
struct Glyph
{
Polygons polygons;
int advance_width, left_side_bearing;
};
// cache for glyph by unicode
using Glyphs = std::map<int, Glyph>;
/// <summary>
/// Load font file into buffer
/// </summary>
/// <param name="file_path">Location of .ttf or .ttc font file</param>
/// <returns>Font object when loaded.</returns>
static std::optional<Font> load_font(const char *file_path);
static std::optional<Font> load_font(std::vector<unsigned char> data);
#ifdef _WIN32
// fix for unknown pointer HFONT
using HFONT = void*;
static std::optional<Font> load_font(HFONT hfont);
#endif // _WIN32
/// <summary>
/// convert letter into polygons
/// </summary>
/// <param name="font">Define fonts</param>
/// <param name="letter">One character to convert</param>
/// <param name="letter">One character defined by unicode codepoint</param>
/// <param name="flatness">Precision of lettter outline curve in conversion to lines</param>
/// <returns>inner polygon cw(outer ccw)</returns>
static Polygons letter2polygons(const Font &font, char letter, float flatness);
static std::optional<Glyph> letter2glyph(const Font &font, int letter, float flatness);
/// <summary>
/// Convert text into polygons
/// </summary>
/// <param name="font">Define fonts</param>
/// <param name="text">Characters to convert</param>
/// <param name="font_prop">User defined property of font</param>
/// <param name="font_prop">User defined property of the font</param>
/// <param name="cache">Cache for letter polygons</param>
/// <returns>Inner polygon cw(outer ccw)</returns>
static Polygons text2polygons(const Font &font, const char *text, const FontProp& font_prop);
static Polygons text2polygons(const Font & font,
const char * text,
const FontProp &font_prop,
Glyphs & cache = Glyphs());
/// <summary>
/// Project 2d point into space

View file

@ -433,7 +433,7 @@ wxString file_wildcards(FileType file_type, const std::string &custom_extension)
/* FT_GCODE */ "G-code files (*.gcode, *.gco, *.g, *.ngc)|*.gcode;*.GCODE;*.gco;*.GCO;*.g;*.G;*.ngc;*.NGC",
/* FT_MODEL */ "Known files (*.stl, *.obj, *.amf, *.xml, *.3mf, *.prusa)|*.stl;*.STL;*.obj;*.OBJ;*.amf;*.AMF;*.xml;*.XML;*.3mf;*.3MF;*.prusa;*.PRUSA",
/* FT_PROJECT */ "Project files (*.3mf, *.amf)|*.3mf;*.3MF;*.amf;*.AMF",
/* FT_FONTS */ "Font files (*.ttf, *.ttc)|*.ttf;*.TTF;*.ttc;*.TTC",
/* FT_FONTS */ "Font files (*.ttf, *.tte, *.ttc, *.dfont)|*.ttf;*.tte;*.ttc;*.dfont;*.TTF;*.TTE;*.TTC;*.DFONT",
/* FT_GALLERY */ "Known files (*.stl, *.obj)|*.stl;*.STL;*.obj;*.OBJ",
/* FT_INI */ "INI files (*.ini)|*.ini;*.INI",

View file

@ -8,6 +8,9 @@
#include "libslic3r/Model.hpp"
#include <wx/font.h>
#include <wx/fontdlg.h>
namespace Slic3r::GUI {
GLGizmoEmboss::GLGizmoEmboss(GLCanvas3D & parent,
@ -21,7 +24,8 @@ GLGizmoEmboss::GLGizmoEmboss(GLCanvas3D & parent,
, m_text_size(255)
, m_text(new char[m_text_size])
, m_scale(0.01f)
, m_emboss(5.f)
, m_emboss(5.f)
, m_volume(nullptr)
{
// TODO: suggest to use https://fontawesome.com/
// (copy & paste) unicode symbols from web
@ -63,18 +67,17 @@ void GLGizmoEmboss::on_render_for_picking() {}
void GLGizmoEmboss::on_render_input_window(float x, float y, float bottom_limit)
{
if (!m_gui_cfg.has_value()) m_gui_cfg.emplace(GuiCfg());
int flag = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize |
ImGuiWindowFlags_NoCollapse;
m_imgui->begin(on_get_name(), flag);
size_t max_font_name = 20; // count characters
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) {
ImGui::PushID((void*)&f.name);
std::string name = (f.name.size() < max_font_name) ?
f.name : (f.name.substr(0,max_font_name - 3) + " ..");
std::string name = (f.name.size() < m_gui_cfg->max_font_name) ?
f.name : (f.name.substr(0,m_gui_cfg->max_font_name - 3) + " ..");
if (ImGui::Selectable(name.c_str(), &f == &current)) {
m_font_selected = &f - &m_font_list.front();
load_font();
@ -90,28 +93,52 @@ void GLGizmoEmboss::on_render_input_window(float x, float y, float bottom_limit)
ImGui::EndCombo();
}
ImGui::SameLine();
m_imgui->disabled_begin(!m_font.has_value() || m_font->count == 1);
if (ImGui::BeginCombo("##font_collection_selector", std::to_string(m_font->index).c_str())) {
for (size_t i = 0; i < m_font->count; ++i) {
ImGui::PushID(1<<10 + i);
if (ImGui::Selectable(std::to_string(i).c_str(), i == m_font->index)) {
m_font->index = i;
if (m_font.has_value()) {
if (ImGui::BeginCombo("##font_collection_selector", std::to_string(m_font->index).c_str())) {
for (size_t i = 0; i < m_font->count; ++i) {
ImGui::PushID(1 << 10 + i);
if (ImGui::Selectable(std::to_string(i).c_str(),
i == m_font->index)) {
m_font->index = i;
}
ImGui::PopID();
}
ImGui::PopID();
ImGui::EndCombo();
}
ImGui::EndCombo();
}
m_imgui->disabled_end();
static std::string fontName;
if (ImGui::Button(_L("choose font").c_str())) {
static wxFontData data; // keep last selected font
wxFontDialog font_dialog(nullptr, data);
font_dialog.SetTitle(_L("Select font FFF"));
if (font_dialog.ShowModal() == wxID_OK) {
data = font_dialog.GetFontData();
wxFont font = data.GetChosenFont();
fontName = boost::nowide::narrow(font.GetFaceName());
m_font = Emboss::load_font(font.GetHFONT());
m_font_glyph_cache.clear();
process();
}
}
if (!fontName.empty()) ImGui::Text(fontName.c_str());
ImGui::SameLine();
draw_add_button();
ImGui::InputFloat("Scale", &m_scale);
ImGui::InputFloat("Emboss", &m_emboss);
ImGui::InputFloat("Flatness", &m_font_prop.flatness);
if (ImGui::InputFloat("Flatness", &m_font_prop.flatness))
m_font_glyph_cache.clear();
ImGui::InputInt("CharGap", &m_font_prop.char_gap);
ImGui::InputInt("LineGap", &m_font_prop.line_gap);
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();
m_imgui->disabled_end();
@ -129,12 +156,12 @@ void GLGizmoEmboss::on_render_input_window(float x, float y, float bottom_limit)
}
// change text size
int max_text_size = m_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 < max_text_size-1) {
while ((index+1) < max_text_size) {
if (m_text.get()[index] == '\0') break;
newData.get()[index] = m_text.get()[index];
++index;
@ -165,7 +192,7 @@ void GLGizmoEmboss::on_set_state()
// Closing gizmo. e.g. selecting another one
if (GLGizmoBase::m_state == GLGizmoBase::Off) {
// refuse outgoing during simlification
// refuse outgoing during text preview
if (false) {
GLGizmoBase::m_state = GLGizmoBase::On;
auto notification_manager = wxGetApp().plater()->get_notification_manager();
@ -175,36 +202,115 @@ void GLGizmoEmboss::on_set_state()
_u8L("ERROR: Wait until ends or Cancel process."));
return;
}
m_volume = nullptr;
} else if (GLGizmoBase::m_state == GLGizmoBase::On) {
// when open by hyperlink it needs to show up
//request_rerender();
}
}
void GLGizmoEmboss::process() {
auto project = std::make_unique<Emboss::ProjectScale>(
std::make_unique<Emboss::ProjectZ>(m_emboss/m_scale), m_scale);
// IMPROVE: Do not use gizmo_event - especialy smth with prefix SLA,
// use Bind into wxGLCanvas?
bool GLGizmoEmboss::gizmo_event(SLAGizmoEventType action,
const Vec2d & mouse_position,
bool shift_down,
bool alt_down,
bool control_down)
{
/* if (action == SLAGizmoEventType::LeftUp) {
const Camera & camera = wxGetApp().plater()->get_camera();
const Selection & selection = m_parent.get_selection();
const ModelObject * mo = m_c->selection_info()->model_object();
const ModelInstance *mi = mo->instances[selection.get_instance_idx()];
const Transform3d & instance_trafo = mi->get_transformation()
.get_matrix();
Polygons polygons = Emboss::text2polygons(*m_font, m_text.get(), m_font_prop);
// Precalculate transformations of individual meshes.
std::vector<Transform3d> trafo_matrices;
for (const ModelVolume *mv : mo->volumes)
if (mv->is_model_part())
trafo_matrices.emplace_back(instance_trafo * mv->get_matrix());
Vec3f normal = Vec3f::Zero();
Vec3f hit = Vec3f::Zero();
size_t facet = 0;
Vec3f closest_hit = Vec3f::Zero();
double closest_hit_squared_distance =
std::numeric_limits<double>::max();
size_t closest_facet = 0;
int closest_hit_mesh_id = -1;
// Cast a ray on all meshes, pick the closest hit and save it for the
// respective mesh
for (int mesh_id = 0; mesh_id < int(trafo_matrices.size());
++mesh_id) {
if (m_c->raycaster()->raycasters()[mesh_id]->unproject_on_mesh(
mouse_position, trafo_matrices[mesh_id], camera, hit,
normal, m_c->object_clipper()->get_clipping_plane(),
&facet)) {
// In case this hit is clipped, skip it.
// Is this hit the closest to the camera so far?
double hit_squared_distance = (camera.get_position() -
trafo_matrices[mesh_id] *
hit.cast<double>())
.squaredNorm();
if (hit_squared_distance < closest_hit_squared_distance) {
closest_hit_squared_distance = hit_squared_distance;
closest_facet = facet;
closest_hit_mesh_id = mesh_id;
closest_hit = hit;
}
}
}
// get intersection
}
*/
return false;
}
void GLGizmoEmboss::process() {
if (!m_font.has_value()) return;
Polygons polygons = Emboss::text2polygons(*m_font, m_text.get(), m_font_prop, m_font_glyph_cache);
if (polygons.empty()) return;
auto project = std::make_unique<Emboss::ProjectScale>(
std::make_unique<Emboss::ProjectZ>(m_emboss/m_scale), m_scale);
indexed_triangle_set its = Emboss::polygons2model(polygons, *project);
if (its.indices.empty()) return;
// add object
TriangleMesh tm(its);
TriangleMesh tm(std::move(its));
tm.repair();
tm.WriteOBJFile("text_preview.obj");
//tm.WriteOBJFile("text_preview.obj");
const Selection &selection = m_parent.get_selection();
int object_idx = selection.get_object_idx();
ModelObject * obj = wxGetApp().plater()->model().objects[object_idx];
ModelVolume * v = obj->volumes.front();
v->set_mesh(tm);
v->set_new_unique_id();
obj->invalidate_bounding_box();
//if (m_volume != nullptr) {
// // TODO: fix index of m_volume
// size_t m_volume_index = obj->volumes.size() - 1;
// obj->delete_volume(m_volume_index);
//}
//m_volume = obj->add_volume(std::move(tm), ModelVolumeType::MODEL_PART);
if (m_volume == nullptr) {
m_volume = obj->add_volume(std::move(tm), ModelVolumeType::MODEL_PART);
} else {
m_volume->set_mesh(std::move(tm));
m_volume->set_new_unique_id();
m_volume->translate(-m_volume->source.mesh_offset);
m_volume->center_geometry_after_creation(true);
m_volume->calculate_convex_hull();
m_volume->get_object()->invalidate_bounding_box();
}
m_parent.reload_scene(true);
}
@ -235,7 +341,7 @@ void GLGizmoEmboss::draw_add_button() {
font_list.emplace_back(name, path);
}
// set last added font as active
m_font_selected = m_font_list.size() - 1;
m_font_selected = m_font_list.size() + font_list.size() - 1;
add_fonts(font_list);
load_font();
}
@ -250,6 +356,7 @@ bool GLGizmoEmboss::load_font()
{
auto font_path = m_font_list[m_font_selected].path.c_str();
m_font = Emboss::load_font(font_path);
m_font_glyph_cache.clear();
return m_font.has_value();
}
@ -279,5 +386,4 @@ void GLGizmoEmboss::add_fonts(const Emboss::FontList &font_list) {
sort_fonts();
}
} // namespace Slic3r::GUI

View file

@ -4,11 +4,14 @@
// Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code,
// which overrides our localization "L" macro.
#include "GLGizmoBase.hpp"
#include "GLGizmosCommon.hpp"
#include "admesh/stl.h" // indexed_triangle_set
#include <optional>
#include <memory>
#include "libslic3r/Emboss.hpp"
#include "libslic3r/Point.hpp"
namespace Slic3r {
class ModelVolume;
@ -19,6 +22,8 @@ class GLGizmoEmboss : public GLGizmoBase
public:
GLGizmoEmboss(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
virtual ~GLGizmoEmboss();
// pseudo virtual function, no inheritance
virtual bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down);
protected:
virtual bool on_init() override;
virtual std::string on_get_name() const override;
@ -27,7 +32,7 @@ protected:
virtual void on_render_input_window(float x, float y, float bottom_limit) override;
virtual bool on_is_activable() const override;
virtual bool on_is_selectable() const override { return true; }
virtual void on_set_state() override;
virtual void on_set_state() override;
private:
void process();
@ -42,7 +47,8 @@ private:
// so the change takes effect. (info by GLGizmoFdmSupports.hpp)
struct GuiCfg
{
const size_t max_font_name = 20; // count characters
GuiCfg() = default;
};
std::optional<GuiCfg> m_gui_cfg;
@ -50,14 +56,28 @@ private:
size_t m_font_selected;// index to m_font_list
std::optional<Emboss::Font> m_font;
Emboss::Glyphs m_font_glyph_cache;
size_t m_text_size;
std::unique_ptr<char[]> m_text;
Emboss::FontProp m_font_prop;
// text position
struct Orientation
{
Vec3f origin = Vec3f(0.f, 0.f, 0.f);
Vec3f normal = Vec3f(0.f, 0.f, 1.f);
Vec3f up = Vec3f(0.f, 1.f, 0.f);
Orientation() = default;
};
Orientation m_orientation;
float m_scale;
float m_emboss;
// actual volume
ModelVolume *m_volume;
};
} // namespace GUI

View file

@ -54,7 +54,7 @@ TEST_CASE("Add TriangleMeshes", "[MeshBoolean]")
Polygons ttf2polygons(const char * font_name, char letter, float flatness = 1.f) {
auto font = Emboss::load_font(font_name);
if (!font.has_value()) return Polygons();
return Emboss::letter2polygons(*font, letter, flatness);
return Emboss::letter2glyph(*font, letter, flatness)->polygons;
}
#include "libslic3r/SVG.hpp"