Add Loading fonts file
Add visualization of national characters(wchar)
This commit is contained in:
parent
026ad24b64
commit
48f1be6ccc
@ -1,5 +1,6 @@
|
|||||||
#include "Emboss.hpp"
|
#include "Emboss.hpp"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
|
#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
|
||||||
#include "imgui/imstb_truetype.h" // stbtt_fontinfo
|
#include "imgui/imstb_truetype.h" // stbtt_fontinfo
|
||||||
@ -145,7 +146,8 @@ Polygons Emboss::letter2polygons(const Font &font, char letter)
|
|||||||
return glyph_opt->polygons;
|
return glyph_opt->polygons;
|
||||||
}
|
}
|
||||||
|
|
||||||
Polygons Emboss::text2polygons(const Font &font, const std::string &text)
|
#include <boost\nowide\convert.hpp>
|
||||||
|
Polygons Emboss::text2polygons(const Font &font, const char *text)
|
||||||
{
|
{
|
||||||
auto font_info_opt = Privat::load_font_info(font);
|
auto font_info_opt = Privat::load_font_info(font);
|
||||||
if (!font_info_opt.has_value()) return Polygons();
|
if (!font_info_opt.has_value()) return Polygons();
|
||||||
@ -153,10 +155,16 @@ Polygons Emboss::text2polygons(const Font &font, const std::string &text)
|
|||||||
|
|
||||||
Point cursor(0, 0);
|
Point cursor(0, 0);
|
||||||
Polygons result;
|
Polygons result;
|
||||||
for (const char &letter : text) {
|
|
||||||
if (letter == '\0') break;
|
|
||||||
|
|
||||||
auto glyph_opt = Privat::get_glyph(*font_info_opt, (int) letter, font.flatness);
|
std::wstring ws = boost::nowide::widen(text);
|
||||||
|
for (wchar_t wc: ws){
|
||||||
|
if (wc == '\n') {
|
||||||
|
cursor.x() = 0;
|
||||||
|
cursor.y() -= font.ascent - font.descent + font.linegap;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int unicode = static_cast<int>(wc);
|
||||||
|
auto glyph_opt = Privat::get_glyph(*font_info_opt, unicode, font.flatness);
|
||||||
if (!glyph_opt.has_value()) continue;
|
if (!glyph_opt.has_value()) continue;
|
||||||
|
|
||||||
// move glyph to cursor position
|
// move glyph to cursor position
|
||||||
@ -323,7 +331,7 @@ void its_remove_edge_triangles(indexed_triangle_set &its)
|
|||||||
std::sort(rem.begin(), rem.end());
|
std::sort(rem.begin(), rem.end());
|
||||||
uint32_t offset = 0;
|
uint32_t offset = 0;
|
||||||
for (uint32_t i : rem) {
|
for (uint32_t i : rem) {
|
||||||
its.indices.erase(its.indices.begin() + i - offset);
|
its.indices.erase(its.indices.begin() + (i - offset));
|
||||||
++offset;
|
++offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ public:
|
|||||||
/// convert letter into polygons
|
/// convert letter into polygons
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="font">Define fonts</param>
|
/// <param name="font">Define fonts</param>
|
||||||
/// <param name="letter">Character to convert</param>
|
/// <param name="letter">One character to convert</param>
|
||||||
/// <returns>inner polygon ccw(outer cw)</returns>
|
/// <returns>inner polygon ccw(outer cw)</returns>
|
||||||
static Polygons letter2polygons(const Font &font, char letter);
|
static Polygons letter2polygons(const Font &font, char letter);
|
||||||
|
|
||||||
@ -63,9 +63,9 @@ public:
|
|||||||
/// Convert text into polygons
|
/// Convert text into polygons
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="font">Define fonts</param>
|
/// <param name="font">Define fonts</param>
|
||||||
/// <param name="letter">Character to convert</param>
|
/// <param name="text">Characters to convert</param>
|
||||||
/// <returns>inner polygon ccw(outer cw)</returns>
|
/// <returns>inner polygon ccw(outer cw)</returns>
|
||||||
static Polygons text2polygons(const Font &font, const std::string &text);
|
static Polygons text2polygons(const Font &font, const char *text);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Project 2d point into space
|
/// Project 2d point into space
|
||||||
|
@ -433,6 +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_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_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_PROJECT */ "Project files (*.3mf, *.amf)|*.3mf;*.3MF;*.amf;*.AMF",
|
||||||
|
/* FT_FONTS */ "Font files (*.ttf, *.ttc)|*.ttf;*.TTF;*.ttc;*.TTC",
|
||||||
/* FT_GALLERY */ "Known files (*.stl, *.obj)|*.stl;*.STL;*.obj;*.OBJ",
|
/* FT_GALLERY */ "Known files (*.stl, *.obj)|*.stl;*.STL;*.obj;*.OBJ",
|
||||||
|
|
||||||
/* FT_INI */ "INI files (*.ini)|*.ini;*.INI",
|
/* FT_INI */ "INI files (*.ini)|*.ini;*.INI",
|
||||||
|
@ -59,6 +59,7 @@ enum FileType
|
|||||||
FT_GCODE,
|
FT_GCODE,
|
||||||
FT_MODEL,
|
FT_MODEL,
|
||||||
FT_PROJECT,
|
FT_PROJECT,
|
||||||
|
FT_FONTS,
|
||||||
FT_GALLERY,
|
FT_GALLERY,
|
||||||
|
|
||||||
FT_INI,
|
FT_INI,
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
#include "slic3r/GUI/Plater.hpp"
|
#include "slic3r/GUI/Plater.hpp"
|
||||||
|
|
||||||
#include "libslic3r/Model.hpp"
|
#include "libslic3r/Model.hpp"
|
||||||
#include "libslic3r/Emboss.hpp"
|
|
||||||
|
|
||||||
namespace Slic3r::GUI {
|
namespace Slic3r::GUI {
|
||||||
|
|
||||||
@ -15,14 +14,22 @@ GLGizmoEmboss::GLGizmoEmboss(GLCanvas3D & parent,
|
|||||||
const std::string &icon_filename,
|
const std::string &icon_filename,
|
||||||
unsigned int sprite_id)
|
unsigned int sprite_id)
|
||||||
: GLGizmoBase(parent, icon_filename, sprite_id)
|
: GLGizmoBase(parent, icon_filename, sprite_id)
|
||||||
, m_fonts({{"NotoSans Regular",
|
, m_fonts({
|
||||||
Slic3r::resources_dir() + "/fonts/NotoSans-Regular.ttf"},
|
{"NotoSans Regular", Slic3r::resources_dir() + "/fonts/NotoSans-Regular.ttf"},
|
||||||
|
{"NotoSans CJK", Slic3r::resources_dir() + "/fonts/NotoSansCJK-Regular.ttc"},
|
||||||
|
//{"Font Awsome", Slic3r::resources_dir() + "/fonts/fa-solid-900.ttf"},
|
||||||
{"Arial", "C:/windows/fonts/arialbd.ttf"}})
|
{"Arial", "C:/windows/fonts/arialbd.ttf"}})
|
||||||
, m_selected(1)
|
, m_fonts_selected(0)
|
||||||
, m_text(_u8L("Embossed text"))
|
, m_text_size(255)
|
||||||
|
, m_text(new char[m_text_size])
|
||||||
|
, m_scale(0.01f)
|
||||||
|
, m_emboss(5.f)
|
||||||
{
|
{
|
||||||
|
load_font();
|
||||||
// TODO: suggest to use https://fontawesome.com/
|
// TODO: suggest to use https://fontawesome.com/
|
||||||
m_text.reserve(255);
|
int index = 0;
|
||||||
|
for (char &c : _u8L("Embossed text")) { m_text[index++] = c; }
|
||||||
|
m_text[index] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
GLGizmoEmboss::~GLGizmoEmboss() {}
|
GLGizmoEmboss::~GLGizmoEmboss() {}
|
||||||
@ -47,64 +54,71 @@ void GLGizmoEmboss::on_render_input_window(float x, float y, float bottom_limit)
|
|||||||
int flag = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize |
|
int flag = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize |
|
||||||
ImGuiWindowFlags_NoCollapse;
|
ImGuiWindowFlags_NoCollapse;
|
||||||
m_imgui->begin(on_get_name(), flag);
|
m_imgui->begin(on_get_name(), flag);
|
||||||
ImGui::Text("welcome in emboss text");
|
|
||||||
auto& current = m_fonts[m_selected];
|
auto& current = m_fonts[m_fonts_selected];
|
||||||
if (ImGui::BeginCombo("##font_selector", current.name.c_str())) {
|
if (ImGui::BeginCombo("##font_selector", current.name.c_str())) {
|
||||||
for (const MyFont &f : m_fonts) {
|
for (const MyFont &f : m_fonts) {
|
||||||
ImGui::PushID((void*)&f.name);
|
ImGui::PushID((void*)&f.name);
|
||||||
if (ImGui::Selectable(f.name.c_str(), &f == ¤t)) {
|
if (ImGui::Selectable(f.name.c_str(), &f == ¤t)) {
|
||||||
m_selected = &f - &m_fonts.front();
|
m_fonts_selected = &f - &m_fonts.front();
|
||||||
|
load_font();
|
||||||
}
|
}
|
||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
}
|
}
|
||||||
ImGui::EndCombo();
|
ImGui::EndCombo();
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::Button("Add");
|
m_imgui->disabled_begin(!m_font.has_value() || m_font->count == 1);
|
||||||
static float scale = 0.01f;
|
if (ImGui::BeginCombo("##font_collection_selector", std::to_string(m_font->index).c_str())) {
|
||||||
ImGui::InputFloat("Scale", &scale);
|
for (size_t i = 0; i < m_font->count; ++i) {
|
||||||
static float emboss = 100.f;
|
ImGui::PushID(1<<10 + i);
|
||||||
ImGui::InputFloat("Emboss", &emboss);
|
if (ImGui::Selectable(std::to_string(i).c_str(), i == m_font->index)) {
|
||||||
|
m_font->index = i;
|
||||||
if(ImGui::Button("Preview")){
|
|
||||||
|
|
||||||
auto project = std::make_unique<Emboss::ProjectScale>(
|
|
||||||
std::make_unique<Emboss::ProjectZ>(emboss)
|
|
||||||
,scale);
|
|
||||||
|
|
||||||
auto font_path = m_fonts[m_selected].file_path.c_str();
|
|
||||||
auto font_opt = Emboss::load_font(font_path);
|
|
||||||
if (font_opt.has_value()) {
|
|
||||||
Polygons polygons = Emboss::text2polygons(*font_opt, m_text);
|
|
||||||
indexed_triangle_set its = Emboss::polygons2model(polygons, *project);
|
|
||||||
// add object
|
|
||||||
TriangleMesh tm(its);
|
|
||||||
tm.repair();
|
|
||||||
|
|
||||||
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();
|
|
||||||
m_parent.reload_scene(true);
|
|
||||||
}
|
}
|
||||||
|
ImGui::PopID();
|
||||||
}
|
}
|
||||||
|
ImGui::EndCombo();
|
||||||
|
}
|
||||||
|
m_imgui->disabled_end();
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
draw_add_button();
|
||||||
|
|
||||||
|
ImGui::InputFloat("Scale", &m_scale);
|
||||||
|
ImGui::InputFloat("Emboss", &m_emboss);
|
||||||
|
m_imgui->disabled_begin(!m_font.has_value());
|
||||||
|
if (ImGui::Button("Preview")) process();
|
||||||
|
m_imgui->disabled_end();
|
||||||
ImVec2 input_size(-FLT_MIN, ImGui::GetTextLineHeight() * 6);
|
ImVec2 input_size(-FLT_MIN, ImGui::GetTextLineHeight() * 6);
|
||||||
ImGuiInputTextFlags flags =
|
ImGuiInputTextFlags flags =
|
||||||
ImGuiInputTextFlags_::ImGuiInputTextFlags_AllowTabInput
|
ImGuiInputTextFlags_::ImGuiInputTextFlags_AllowTabInput
|
||||||
| ImGuiInputTextFlags_::ImGuiInputTextFlags_AutoSelectAll
|
| ImGuiInputTextFlags_::ImGuiInputTextFlags_AutoSelectAll
|
||||||
|
//| ImGuiInputTextFlags_::ImGuiInputTextFlags_CallbackResize
|
||||||
//|ImGuiInputTextFlags_::ImGuiInputTextFlags_CtrlEnterForNewLine
|
//|ImGuiInputTextFlags_::ImGuiInputTextFlags_CtrlEnterForNewLine
|
||||||
;
|
;
|
||||||
if (ImGui::InputTextMultiline("##Text", (char *) m_text.c_str(),
|
|
||||||
m_text.capacity() + 1, input_size, flags)) {
|
|
||||||
|
|
||||||
|
|
||||||
|
if (ImGui::InputTextMultiline("##Text", m_text.get(), m_text_size, input_size, flags)) {
|
||||||
|
process();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// change text size
|
||||||
|
int max_text_size = 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) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw 2d triangle in IMGUI
|
||||||
ImVec2 t0(25, 25);
|
ImVec2 t0(25, 25);
|
||||||
ImVec2 t1(150, 5);
|
ImVec2 t1(150, 5);
|
||||||
ImVec2 t2(10, 100);
|
ImVec2 t2(10, 100);
|
||||||
@ -142,9 +156,72 @@ void GLGizmoEmboss::on_set_state()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLGizmoEmboss::process() {
|
||||||
|
auto project = std::make_unique<Emboss::ProjectScale>(
|
||||||
|
std::make_unique<Emboss::ProjectZ>(m_emboss/m_scale), m_scale);
|
||||||
|
|
||||||
|
Polygons polygons = Emboss::text2polygons(*m_font, m_text.get());
|
||||||
|
if (polygons.empty()) return;
|
||||||
|
|
||||||
|
indexed_triangle_set its = Emboss::polygons2model(polygons, *project);
|
||||||
|
if (its.indices.empty()) return;
|
||||||
|
|
||||||
|
// add object
|
||||||
|
TriangleMesh tm(its);
|
||||||
|
tm.repair();
|
||||||
|
|
||||||
|
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();
|
||||||
|
m_parent.reload_scene(true);
|
||||||
|
}
|
||||||
|
|
||||||
void GLGizmoEmboss::close() {
|
void GLGizmoEmboss::close() {
|
||||||
// close gizmo == open it again
|
// close gizmo == open it again
|
||||||
GLGizmosManager &gizmos_mgr = m_parent.get_gizmos_manager();
|
GLGizmosManager &gizmos_mgr = m_parent.get_gizmos_manager();
|
||||||
gizmos_mgr.open_gizmo(GLGizmosManager::EType::Simplify);
|
gizmos_mgr.open_gizmo(GLGizmosManager::EType::Simplify);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLGizmoEmboss::draw_add_button() {
|
||||||
|
if (ImGui::Button(_u8L("Add").c_str())) {
|
||||||
|
wxArrayString input_files;
|
||||||
|
wxString fontDir = wxEmptyString;
|
||||||
|
wxString selectedFile = wxEmptyString;
|
||||||
|
wxFileDialog dialog(
|
||||||
|
nullptr, _L("Choose one or more files (TTF, TTC):"),
|
||||||
|
fontDir, selectedFile,
|
||||||
|
file_wildcards(FT_FONTS),
|
||||||
|
wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST);
|
||||||
|
if (dialog.ShowModal() == wxID_OK) dialog.GetPaths(input_files);
|
||||||
|
if (input_files.IsEmpty()) return;
|
||||||
|
|
||||||
|
for (auto &input_file : input_files) {
|
||||||
|
std::string name = input_file.AfterLast('\\').c_str();
|
||||||
|
std::string path = input_file.c_str();
|
||||||
|
m_fonts.emplace_back(name, path);
|
||||||
|
}
|
||||||
|
// set last added font as active
|
||||||
|
m_fonts_selected = m_fonts.size() - 1;
|
||||||
|
load_font();
|
||||||
|
//load_files(input_files);
|
||||||
|
}
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text("add file with font(.ttf, .ttc)");
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLGizmoEmboss::load_font()
|
||||||
|
{
|
||||||
|
auto font_path = m_fonts[m_fonts_selected].file_path.c_str();
|
||||||
|
m_font = Emboss::load_font(font_path);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Slic3r::GUI
|
} // namespace Slic3r::GUI
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
#include <optional>
|
#include <optional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
#include "libslic3r/Emboss.hpp"
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
class ModelVolume;
|
class ModelVolume;
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
@ -28,7 +30,10 @@ protected:
|
|||||||
virtual void on_set_state() override;
|
virtual void on_set_state() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void process();
|
||||||
void close();
|
void close();
|
||||||
|
void draw_add_button();
|
||||||
|
void load_font();
|
||||||
|
|
||||||
// This configs holds GUI layout size given by translated texts.
|
// This configs holds GUI layout size given by translated texts.
|
||||||
// etc. When language changes, GUI is recreated and this class constructed again,
|
// etc. When language changes, GUI is recreated and this class constructed again,
|
||||||
@ -50,9 +55,15 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::vector<MyFont> m_fonts;
|
std::vector<MyFont> m_fonts;
|
||||||
size_t m_selected;// index to m_fonts
|
size_t m_fonts_selected;// index to m_fonts
|
||||||
|
|
||||||
std::string m_text;
|
std::optional<Emboss::Font> m_font;
|
||||||
|
|
||||||
|
size_t m_text_size;
|
||||||
|
std::unique_ptr<char[]> m_text;
|
||||||
|
|
||||||
|
float m_scale;
|
||||||
|
float m_emboss;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace GUI
|
} // namespace GUI
|
||||||
|
Loading…
Reference in New Issue
Block a user