Load font name by STBTT
This commit is contained in:
parent
df50110ba7
commit
20645264f8
4 changed files with 166 additions and 81 deletions
src
|
@ -11,19 +11,21 @@
|
|||
using namespace Slic3r;
|
||||
|
||||
Emboss::FontItem::FontItem(const std::string &name, const std::string &path)
|
||||
: name(name)
|
||||
, path(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
|
||||
{
|
||||
public:
|
||||
public:
|
||||
Privat() = delete;
|
||||
|
||||
static std::optional<stbtt_fontinfo> load_font_info(const Emboss::Font &font);
|
||||
|
@ -394,6 +396,7 @@ std::optional<Emboss::Font> Emboss::load_font(std::vector<unsigned char> data)
|
|||
while (font_offset >= 0) {
|
||||
font_offset = stbtt_GetFontOffsetForIndex(res.buffer.data(), index++);
|
||||
}
|
||||
--index; // last one is bad
|
||||
// at least one font must be inside collection
|
||||
if (index < 1) {
|
||||
std::cerr << "There is no font collection inside file.";
|
||||
|
@ -405,10 +408,29 @@ std::optional<Emboss::Font> Emboss::load_font(std::vector<unsigned char> data)
|
|||
|
||||
auto font_info = Privat::load_font_info(res);
|
||||
if (!font_info.has_value()) return {};
|
||||
|
||||
const stbtt_fontinfo *info = &(*font_info);
|
||||
// load information about line gap
|
||||
stbtt_GetFontVMetrics(&(*font_info), &res.ascent, &res.descent,
|
||||
&res.linegap);
|
||||
stbtt_GetFontVMetrics(info, &res.ascent, &res.descent, &res.linegap);
|
||||
|
||||
// TrueType Reference Manual - The 'name' table https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6name.html
|
||||
// OpenType™ Specification - The Naming Table http://www.microsoft.com/typography/otspec/name.htm
|
||||
int length = 0;
|
||||
//PLATFORM_ID_UNICODE PLATFORM_ID_MAC PLATFORM_ID_ISO PLATFORM_ID_MICROSOFT
|
||||
int platformId = STBTT_PLATFORM_ID_MICROSOFT;
|
||||
// UNICODE_EID_UNICODE_1_0 UNICODE_EID_UNICODE_1_1 UNICODE_EID_ISO_10646 UNICODE_EID_UNICODE_2_0_BMP
|
||||
// UNICODE_EID_UNICODE_2_0_FULL MS_EID_SYMBOL MS_EID_UNICODE_BMP MS_EID_SHIFTJIS MS_EID_UNICODE_FULL
|
||||
// MAC_EID_ROMAN MAC_EID_JAPANESE MAC_EID_CHINESE_TRAD MAC_EID_KOREAN MAC_EID_ARABIC MAC_EID_HEBREW MAC_EID_GREEK
|
||||
// MAC_EID_RUSSIAN
|
||||
int encodingID = STBTT_MS_EID_SYMBOL;
|
||||
// MS_LANG_ENGLISH MS_LANG_CHINESE MS_LANG_DUTCH MS_LANG_FRENCH MS_LANG_GERMAN MS_LANG_HEBREW MS_LANG_ITALIAN
|
||||
// MS_LANG_JAPANESE MS_LANG_KOREAN MS_LANG_RUSSIAN MS_LANG_SPANISH MS_LANG_SWEDISH MAC_LANG_ENGLISH
|
||||
// MAC_LANG_ARABIC MAC_LANG_DUTCH MAC_LANG_FRENCH MAC_LANG_GERMAN MAC_LANG_HEBREW MAC_LANG_ITALIAN
|
||||
// MAC_LANG_JAPANESE MAC_LANG_KOREAN MAC_LANG_RUSSIAN MAC_LANG_SPANISH MAC_LANG_SWEDISH
|
||||
// MAC_LANG_CHINESE_SIMPLIFIED MAC_LANG_CHINESE_TRAD
|
||||
int languageID = STBTT_MS_LANG_ENGLISH;
|
||||
int nameID = 4; // human readable - http://www.microsoft.com/typography/otspec/name.htm
|
||||
const char *name_char = stbtt_GetFontNameString(info, &length, platformId, encodingID, languageID, nameID);
|
||||
res.name = std::string(name_char, length);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -482,14 +504,10 @@ std::optional<Emboss::Glyph> Emboss::letter2glyph(const Font &font,
|
|||
return Privat::get_glyph(*font_info_opt, (int) letter, flatness);
|
||||
}
|
||||
|
||||
Polygons Emboss::text2polygons(const Font & font,
|
||||
Polygons Emboss::text2polygons(Font & font,
|
||||
const char * text,
|
||||
const FontProp &font_prop,
|
||||
Glyphs * cache)
|
||||
const FontProp &font_prop)
|
||||
{
|
||||
Glyphs tmp;
|
||||
if (cache == nullptr) cache = &tmp;
|
||||
|
||||
std::optional<stbtt_fontinfo> font_info_opt;
|
||||
|
||||
Point cursor(0, 0);
|
||||
|
@ -504,8 +522,9 @@ Polygons Emboss::text2polygons(const Font & font,
|
|||
}
|
||||
int unicode = static_cast<int>(wc);
|
||||
std::optional<Glyph> glyph_opt;
|
||||
auto glyph_item = cache->find(unicode);
|
||||
if (glyph_item != cache->end()) glyph_opt = glyph_item->second;
|
||||
auto glyph_item = font.cache.find(unicode);
|
||||
if (glyph_item != font.cache.end())
|
||||
glyph_opt = glyph_item->second;
|
||||
else {
|
||||
if (!font_info_opt.has_value()) {
|
||||
font_info_opt = Privat::load_font_info(font);
|
||||
|
@ -514,9 +533,10 @@ Polygons Emboss::text2polygons(const Font & font,
|
|||
}
|
||||
glyph_opt = Privat::get_glyph(*font_info_opt, unicode,
|
||||
font_prop.flatness);
|
||||
// IMPROVE: multiple loadig glyph without data
|
||||
// has definition inside of font?
|
||||
if (!glyph_opt.has_value()) continue;
|
||||
cache->operator[](unicode) = *glyph_opt;
|
||||
font.cache[unicode] = *glyph_opt;
|
||||
}
|
||||
|
||||
// move glyph to cursor position
|
||||
|
|
|
@ -23,8 +23,17 @@ public:
|
|||
{
|
||||
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>;
|
||||
|
||||
|
@ -46,21 +55,6 @@ public:
|
|||
/// <returns>File path to font when found</returns>
|
||||
static std::optional<std::wstring> get_font_path(const std::wstring &font_face_name);
|
||||
|
||||
/// <summary>
|
||||
/// keep information from file about font
|
||||
/// </summary>
|
||||
struct Font
|
||||
{
|
||||
// loaded data from font file
|
||||
std::vector<unsigned char> buffer;
|
||||
|
||||
unsigned int index=0; // index of actual file info in collection
|
||||
unsigned int count=0; // count of fonts in file collection
|
||||
|
||||
// vertical position is "scale*(ascent - descent + lineGap)"
|
||||
int ascent=0, descent=0, linegap=0;
|
||||
};
|
||||
|
||||
// user defined font property
|
||||
struct FontProp
|
||||
{
|
||||
|
@ -83,6 +77,25 @@ public:
|
|||
};
|
||||
// cache for glyph by unicode
|
||||
using Glyphs = std::map<int, Glyph>;
|
||||
|
||||
/// <summary>
|
||||
/// keep information from file about font
|
||||
/// </summary>
|
||||
struct Font
|
||||
{
|
||||
// loaded data from font file
|
||||
std::vector<unsigned char> buffer;
|
||||
|
||||
unsigned int index = 0; // index of actual file info in collection
|
||||
unsigned int count = 0; // count of fonts in file collection
|
||||
|
||||
// vertical position is "scale*(ascent - descent + lineGap)"
|
||||
int ascent = 0, descent = 0, linegap = 0;
|
||||
|
||||
std::string name;
|
||||
|
||||
Emboss::Glyphs cache;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Load font file into buffer
|
||||
|
@ -110,15 +123,13 @@ public:
|
|||
/// <summary>
|
||||
/// Convert text into polygons
|
||||
/// </summary>
|
||||
/// <param name="font">Define fonts</param>
|
||||
/// <param name="font">Define fonts + cache, which could extend</param>
|
||||
/// <param name="text">Characters to convert</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,
|
||||
static Polygons text2polygons(Font & font,
|
||||
const char * text,
|
||||
const FontProp &font_prop,
|
||||
Glyphs * cache = nullptr);
|
||||
const FontProp &font_prop);
|
||||
|
||||
/// <summary>
|
||||
/// Project 2d point into space
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#include <wx/font.h>
|
||||
#include <wx/fontdlg.h>
|
||||
|
||||
namespace Slic3r::GUI {
|
||||
using namespace Slic3r::GUI;
|
||||
|
||||
GLGizmoEmboss::GLGizmoEmboss(GLCanvas3D & parent,
|
||||
const std::string &icon_filename,
|
||||
|
@ -72,46 +72,24 @@ void GLGizmoEmboss::on_render_input_window(float x, float y, float bottom_limit)
|
|||
int flag = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize |
|
||||
ImGuiWindowFlags_NoCollapse;
|
||||
m_imgui->begin(on_get_name(), flag);
|
||||
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() < 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 == ¤t)) {
|
||||
m_font_selected = &f - &m_font_list.front();
|
||||
load_font();
|
||||
process();
|
||||
}
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text((f.name + " " + f.path).c_str());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
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::EndCombo();
|
||||
}
|
||||
ImGui::Text("Selected font is %s END.", m_font->name.c_str());
|
||||
} else {
|
||||
ImGui::Text("No selected font yet.");
|
||||
}
|
||||
draw_font_list();
|
||||
|
||||
|
||||
static std::string os_font;
|
||||
|
||||
// TODO: fix load string each render
|
||||
wxSystemSettings ss;
|
||||
wxFont ssFont = ss.GetFont(wxSYS_ANSI_VAR_FONT);
|
||||
ImGui::Text("Desc %s", std::string(ssFont.GetNativeFontInfoDesc().c_str()).c_str());
|
||||
std::string fontDesc = std::string(ssFont.GetNativeFontInfoDesc().c_str());
|
||||
ImGui::Text("%s", fontDesc.c_str());
|
||||
if (ImGui::Button(_L("Load font").c_str())) {
|
||||
wxFont font = load_wxFont(fontDesc);
|
||||
set_font(font);
|
||||
}
|
||||
|
||||
static std::string fontName;
|
||||
if (ImGui::Button(_L("choose font").c_str())) {
|
||||
|
@ -123,12 +101,11 @@ void GLGizmoEmboss::on_render_input_window(float x, float y, float bottom_limit)
|
|||
wxFont font2 = data.GetChosenFont();
|
||||
wxString fontDesc2 = font2.GetNativeFontInfoDesc();
|
||||
fontName = std::string(fontDesc2.c_str());
|
||||
fontName = "Arial 10";
|
||||
|
||||
wxString fontDesc(fontName);
|
||||
wxFont font(fontDesc);
|
||||
//font.IsOk()
|
||||
// m_font = Emboss::load_font(font.GetHFONT()); // load font os specific
|
||||
m_font_glyph_cache.clear();
|
||||
process();
|
||||
}
|
||||
}
|
||||
|
@ -140,7 +117,7 @@ void GLGizmoEmboss::on_render_input_window(float x, float y, float bottom_limit)
|
|||
ImGui::InputFloat("Scale", &m_scale);
|
||||
ImGui::InputFloat("Emboss", &m_emboss);
|
||||
if (ImGui::InputFloat("Flatness", &m_font_prop.flatness))
|
||||
m_font_glyph_cache.clear();
|
||||
if(m_font.has_value()) m_font->cache.clear();
|
||||
ImGui::InputInt("CharGap", &m_font_prop.char_gap);
|
||||
ImGui::InputInt("LineGap", &m_font_prop.line_gap);
|
||||
|
||||
|
@ -148,8 +125,6 @@ void GLGizmoEmboss::on_render_input_window(float x, float y, float bottom_limit)
|
|||
//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();
|
||||
|
@ -286,7 +261,7 @@ bool GLGizmoEmboss::gizmo_event(SLAGizmoEventType action,
|
|||
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);
|
||||
Polygons polygons = Emboss::text2polygons(*m_font, m_text.get(), m_font_prop);
|
||||
if (polygons.empty()) return;
|
||||
|
||||
auto project = std::make_unique<Emboss::ProjectScale>(
|
||||
|
@ -365,14 +340,87 @@ void GLGizmoEmboss::draw_add_button() {
|
|||
}
|
||||
}
|
||||
|
||||
void GLGizmoEmboss::draw_font_list()
|
||||
{
|
||||
auto ¤t = 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() < 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 == ¤t)) {
|
||||
m_font_selected = &f - &m_font_list.front();
|
||||
load_font();
|
||||
process();
|
||||
}
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text((f.name + " " + f.path).c_str());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
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::EndCombo();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
void GLGizmoEmboss::set_font(const wxFont &font) {
|
||||
//std::string m_font_name = std::string((
|
||||
// font.GetFamilyString() + " " +
|
||||
// font.GetStyleString() + " " +
|
||||
// font.GetWeightString()
|
||||
// ).c_str());
|
||||
#ifdef _WIN32
|
||||
m_font = Emboss::load_font(font.GetHFONT());
|
||||
#elif __linux__
|
||||
// use file path
|
||||
#elif __APPLE__
|
||||
const wxNativeFontInfo *info = font.GetNativeFontInfo();
|
||||
CTFontDescriptorRef descriptor = info3->GetCTFontDescriptor();
|
||||
CFDictionaryRef attribs = CTFontDescriptorCopyAttributes(descriptor);
|
||||
CFStringRef url = (CFStringRef)CTFontDescriptorCopyAttribute(descriptor, kCTFontURLAttribute);
|
||||
std::string str(CFStringGetCStringPtr(CFURLGetString(anUrl),kCFStringEncodingUTF8));
|
||||
m_font = Emboss::load_font(str);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string GLGizmoEmboss::store_wxFont(const wxFont &font)
|
||||
{
|
||||
//wxString os = wxPlatformInfo::Get().GetOperatingSystemIdName();
|
||||
wxString font_descriptor = font.GetNativeFontInfoDesc();
|
||||
return std::string(font_descriptor.c_str());
|
||||
}
|
||||
|
||||
wxFont GLGizmoEmboss::load_wxFont(const std::string &font_descriptor)
|
||||
{
|
||||
wxString font_descriptor_wx(font_descriptor);
|
||||
return wxFont(font_descriptor_wx);
|
||||
}
|
||||
|
||||
void GLGizmoEmboss::sort_fonts() {
|
||||
// initialize original index locations
|
||||
std::vector<size_t> idx(m_font_list.size());
|
||||
|
@ -398,5 +446,3 @@ void GLGizmoEmboss::add_fonts(const Emboss::FontList &font_list) {
|
|||
m_font_list.insert(m_font_list.end(), font_list.begin(), font_list.end());
|
||||
sort_fonts();
|
||||
}
|
||||
|
||||
} // namespace Slic3r::GUI
|
||||
|
|
|
@ -37,8 +37,17 @@ protected:
|
|||
private:
|
||||
void process();
|
||||
void close();
|
||||
void draw_font_list();
|
||||
void draw_add_button();
|
||||
bool load_font();
|
||||
|
||||
// os specific set of wxFont
|
||||
void set_font(const wxFont &font);
|
||||
|
||||
// serialize / deserialize font
|
||||
static std::string store_wxFont(const wxFont& font);
|
||||
static wxFont load_wxFont(const std::string &font_descriptor);
|
||||
|
||||
void sort_fonts();
|
||||
void add_fonts(const Emboss::FontList &font_list);
|
||||
|
||||
|
@ -56,7 +65,6 @@ 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;
|
||||
|
|
Loading…
Reference in a new issue