add index of font inside of collection to FontProp(font property) + serialization/deserialization (3mf + appConfig)
separate glyph cache from FontFile
This commit is contained in:
parent
8022c64209
commit
18d269506a
@ -21,8 +21,6 @@ class Private
|
||||
{
|
||||
public:
|
||||
Private() = delete;
|
||||
|
||||
static std::optional<stbtt_fontinfo> load_font_info(const Emboss::FontFile &font);
|
||||
static std::optional<stbtt_fontinfo> load_font_info(const unsigned char *data, unsigned int index = 0);
|
||||
static std::optional<Emboss::Glyph> get_glyph(stbtt_fontinfo &font_info, int unicode_letter, float flatness);
|
||||
static std::optional<Emboss::Glyph> get_glyph(int unicode, const Emboss::FontFile &font, const FontProp &font_prop,
|
||||
@ -42,11 +40,6 @@ public:
|
||||
static Point to_point(const stbtt__point &point);
|
||||
};
|
||||
|
||||
std::optional<stbtt_fontinfo> Private::load_font_info(const Emboss::FontFile &font)
|
||||
{
|
||||
return load_font_info(font.buffer.data(), font.index);
|
||||
}
|
||||
|
||||
std::optional<stbtt_fontinfo> Private::load_font_info(
|
||||
const unsigned char *data, unsigned int index)
|
||||
{
|
||||
@ -137,7 +130,10 @@ std::optional<Emboss::Glyph> Private::get_glyph(
|
||||
return glyph_item->second;
|
||||
|
||||
if (!font_info_opt.has_value()) {
|
||||
font_info_opt = Private::load_font_info(font);
|
||||
int font_index = font_prop.collection_number.has_value()?
|
||||
*font_prop.collection_number : 0;
|
||||
if (font_index >= font.count) return {};
|
||||
font_info_opt = Private::load_font_info(font.data->data(), font_index);
|
||||
// can load font info?
|
||||
if (!font_info_opt.has_value()) return {};
|
||||
}
|
||||
@ -466,16 +462,16 @@ std::optional<std::wstring> Emboss::get_font_path(const std::wstring &font_face_
|
||||
}
|
||||
#endif
|
||||
|
||||
std::unique_ptr<Emboss::FontFile> Emboss::load_font(
|
||||
std::vector<unsigned char> &&data)
|
||||
std::unique_ptr<Emboss::FontFile> Emboss::create_font_file(
|
||||
std::unique_ptr<std::vector<unsigned char>> data)
|
||||
{
|
||||
int collection_size = stbtt_GetNumberOfFonts(data.data());
|
||||
int collection_size = stbtt_GetNumberOfFonts(data->data());
|
||||
// at least one font must be inside collection
|
||||
if (collection_size < 1) {
|
||||
std::cerr << "There is no font collection inside data." << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
auto font_info = Private::load_font_info(data.data());
|
||||
auto font_info = Private::load_font_info(data->data());
|
||||
if (!font_info.has_value()) return nullptr;
|
||||
|
||||
const stbtt_fontinfo *info = &(*font_info);
|
||||
@ -490,7 +486,7 @@ std::unique_ptr<Emboss::FontFile> Emboss::load_font(
|
||||
std::move(data), collection_size, ascent, descent, linegap, units_per_em);
|
||||
}
|
||||
|
||||
std::unique_ptr<Emboss::FontFile> Emboss::load_font(const char *file_path)
|
||||
std::unique_ptr<Emboss::FontFile> Emboss::create_font_file(const char *file_path)
|
||||
{
|
||||
FILE *file = fopen(file_path, "rb");
|
||||
if (file == nullptr) {
|
||||
@ -509,14 +505,13 @@ std::unique_ptr<Emboss::FontFile> Emboss::load_font(const char *file_path)
|
||||
return nullptr;
|
||||
}
|
||||
rewind(file);
|
||||
|
||||
std::vector<unsigned char> buffer(size);
|
||||
size_t count_loaded_bytes = fread((void *) &buffer.front(), 1, size, file);
|
||||
auto buffer = std::make_unique<std::vector<unsigned char>>(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." << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
return load_font(std::move(buffer));
|
||||
return create_font_file(std::move(buffer));
|
||||
}
|
||||
|
||||
|
||||
@ -557,7 +552,7 @@ void * Emboss::can_load(HFONT hfont)
|
||||
return hfont;
|
||||
}
|
||||
|
||||
std::unique_ptr<Emboss::FontFile> Emboss::load_font(HFONT hfont)
|
||||
std::unique_ptr<Emboss::FontFile> Emboss::create_font_file(HFONT hfont)
|
||||
{
|
||||
HDC hdc = ::CreateCompatibleDC(NULL);
|
||||
if (hdc == NULL) {
|
||||
@ -571,16 +566,14 @@ std::unique_ptr<Emboss::FontFile> Emboss::load_font(HFONT hfont)
|
||||
::DeleteDC(hdc);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> buffer(size);
|
||||
size_t loaded_size = ::GetFontData(hdc, dwTable, dwOffset, buffer.data(), size);
|
||||
auto buffer = std::make_unique<std::vector<unsigned char>>(size);
|
||||
size_t loaded_size = ::GetFontData(hdc, dwTable, dwOffset, buffer->data(), size);
|
||||
::DeleteDC(hdc);
|
||||
if (size != loaded_size) {
|
||||
std::cerr << "Different loaded(from HFONT) data size." << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return load_font(std::move(buffer));
|
||||
return create_font_file(std::move(buffer));
|
||||
}
|
||||
#endif // _WIN32
|
||||
|
||||
@ -588,20 +581,22 @@ std::optional<Emboss::Glyph> Emboss::letter2glyph(const FontFile &font,
|
||||
int letter,
|
||||
float flatness)
|
||||
{
|
||||
auto font_info_opt = Private::load_font_info(font);
|
||||
auto font_info_opt = Private::load_font_info(font.data->data(), 0);
|
||||
if (!font_info_opt.has_value()) return {};
|
||||
return Private::get_glyph(*font_info_opt, letter, flatness);
|
||||
}
|
||||
|
||||
ExPolygons Emboss::text2shapes(FontFile & font,
|
||||
ExPolygons Emboss::text2shapes(FontFileWithCache &font_with_cache,
|
||||
const char * text,
|
||||
const FontProp &font_prop)
|
||||
{
|
||||
std::optional<stbtt_fontinfo> font_info_opt;
|
||||
|
||||
assert(font_with_cache.has_value());
|
||||
|
||||
std::optional<stbtt_fontinfo> font_info_opt;
|
||||
Point cursor(0, 0);
|
||||
ExPolygons result;
|
||||
|
||||
const FontFile& font = *font_with_cache.font_file;
|
||||
Emboss::Glyphs& cache = *font_with_cache.cache;
|
||||
std::wstring ws = boost::nowide::widen(text);
|
||||
for (wchar_t wc: ws){
|
||||
if (wc == '\n') {
|
||||
@ -617,14 +612,14 @@ ExPolygons Emboss::text2shapes(FontFile & font,
|
||||
if (wc == '\t') {
|
||||
// '\t' = 4*space => same as imgui
|
||||
const int count_spaces = 4;
|
||||
std::optional<Glyph> space_opt = Private::get_glyph(int(' '), font, font_prop, font.cache, font_info_opt);
|
||||
std::optional<Glyph> space_opt = Private::get_glyph(int(' '), font, font_prop, cache, font_info_opt);
|
||||
if (!space_opt.has_value()) continue;
|
||||
cursor.x() += count_spaces * space_opt->advance_width;
|
||||
continue;
|
||||
}
|
||||
|
||||
int unicode = static_cast<int>(wc);
|
||||
std::optional<Glyph> glyph_opt = Private::get_glyph(unicode, font, font_prop, font.cache, font_info_opt);
|
||||
std::optional<Glyph> glyph_opt = Private::get_glyph(unicode, font, font_prop, cache, font_info_opt);
|
||||
if (!glyph_opt.has_value()) continue;
|
||||
|
||||
// move glyph to cursor position
|
||||
@ -652,9 +647,10 @@ void Emboss::apply_transformation(const FontProp &font_prop,
|
||||
}
|
||||
}
|
||||
|
||||
bool Emboss::is_italic(FontFile &font) {
|
||||
std::optional<stbtt_fontinfo> font_info_opt =
|
||||
Private::load_font_info(font);
|
||||
bool Emboss::is_italic(FontFile &font, int font_index)
|
||||
{
|
||||
if (font_index >= font.count) return false;
|
||||
std::optional<stbtt_fontinfo> font_info_opt = Private::load_font_info(font.data->data(), font_index);
|
||||
|
||||
if (!font_info_opt.has_value()) return false;
|
||||
stbtt_fontinfo *info = &(*font_info_opt);
|
||||
|
@ -59,44 +59,62 @@ public:
|
||||
/// keep information from file about font
|
||||
/// (store file data itself)
|
||||
/// + cache data readed from buffer
|
||||
/// + cache shape of glyphs (optionaly modified)
|
||||
/// </summary>
|
||||
struct FontFile
|
||||
{
|
||||
// loaded data from font file
|
||||
const std::vector<unsigned char> buffer;
|
||||
// must store data size for imgui rasterization
|
||||
// To not store data on heap and To prevent unneccesary copy
|
||||
// data are stored inside unique_ptr
|
||||
std::unique_ptr<std::vector<unsigned char>> data;
|
||||
|
||||
unsigned int index; // index of actual file info in collection
|
||||
const unsigned int count; // count of fonts in file collection
|
||||
// count of fonts when data are collection of fonts
|
||||
unsigned int count;
|
||||
|
||||
// vertical position is "scale*(ascent - descent + lineGap)"
|
||||
const int ascent, descent, linegap;
|
||||
int ascent, descent, linegap;
|
||||
|
||||
// for convert font units to pixel
|
||||
int unit_per_em;
|
||||
|
||||
Emboss::Glyphs cache; // cache of glyphs
|
||||
|
||||
FontFile(std::vector<unsigned char> &&buffer,
|
||||
unsigned int count,
|
||||
int ascent,
|
||||
int descent,
|
||||
int linegap,
|
||||
int unit_per_em
|
||||
)
|
||||
: buffer(std::move(buffer))
|
||||
, index(0) // select default font on index 0
|
||||
FontFile(std::unique_ptr<std::vector<unsigned char>> data,
|
||||
unsigned int count,
|
||||
int ascent,
|
||||
int descent,
|
||||
int linegap,
|
||||
int unit_per_em)
|
||||
: data(std::move(data))
|
||||
, count(count)
|
||||
, ascent(ascent)
|
||||
, descent(descent)
|
||||
, linegap(linegap)
|
||||
, unit_per_em(unit_per_em)
|
||||
{}
|
||||
bool operator==(const FontFile &other) const {
|
||||
return index == other.index &&
|
||||
buffer.size() == other.buffer.size() &&
|
||||
buffer == other.buffer;
|
||||
{
|
||||
assert(this->data != nullptr);
|
||||
}
|
||||
bool operator==(const FontFile &other) const {
|
||||
return count == other.count && ascent == other.ascent &&
|
||||
descent == other.descent && linegap == other.linegap &&
|
||||
data->size() == other.data->size();
|
||||
//&& *data == *other.data;
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Add caching for shape of glyphs
|
||||
/// </summary>
|
||||
struct FontFileWithCache
|
||||
{
|
||||
std::shared_ptr<FontFile> font_file;
|
||||
// cache for glyph shape
|
||||
std::shared_ptr<Emboss::Glyphs> cache;
|
||||
|
||||
FontFileWithCache() : font_file(nullptr), cache(nullptr) {}
|
||||
FontFileWithCache(std::unique_ptr<FontFile> font_file)
|
||||
: font_file(std::move(font_file))
|
||||
, cache(std::make_shared<Emboss::Glyphs>())
|
||||
{}
|
||||
bool has_value() const { return font_file != nullptr && cache != nullptr; }
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@ -104,14 +122,14 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="file_path">Location of .ttf or .ttc font file</param>
|
||||
/// <returns>Font object when loaded.</returns>
|
||||
static std::unique_ptr<FontFile> load_font(const char *file_path);
|
||||
static std::unique_ptr<FontFile> create_font_file(const char *file_path);
|
||||
// data = raw file data
|
||||
static std::unique_ptr<FontFile> load_font(std::vector<unsigned char>&& data);
|
||||
static std::unique_ptr<FontFile> create_font_file(std::unique_ptr<std::vector<unsigned char>> data);
|
||||
#ifdef _WIN32
|
||||
// fix for unknown pointer HFONT
|
||||
using HFONT = void*;
|
||||
static void * can_load(HFONT hfont);
|
||||
static std::unique_ptr<FontFile> load_font(HFONT hfont);
|
||||
static std::unique_ptr<FontFile> create_font_file(HFONT hfont);
|
||||
#endif // _WIN32
|
||||
|
||||
/// <summary>
|
||||
@ -130,7 +148,7 @@ public:
|
||||
/// <param name="text">Characters to convert</param>
|
||||
/// <param name="font_prop">User defined property of the font</param>
|
||||
/// <returns>Inner polygon cw(outer ccw)</returns>
|
||||
static ExPolygons text2shapes(FontFile & font,
|
||||
static ExPolygons text2shapes(FontFileWithCache &font,
|
||||
const char * text,
|
||||
const FontProp &font_prop);
|
||||
|
||||
@ -148,8 +166,9 @@ public:
|
||||
/// search for italic (or oblique), bold italic (or bold oblique)
|
||||
/// </summary>
|
||||
/// <param name="font">Selector of font</param>
|
||||
/// <param name="font_index">Index of font in collection</param>
|
||||
/// <returns>True when the font description contains italic/obligue otherwise False</returns>
|
||||
static bool is_italic(FontFile &font);
|
||||
static bool is_italic(FontFile &font, int font_index = 0);
|
||||
|
||||
/// <summary>
|
||||
/// Project 2d point into space
|
||||
|
@ -163,6 +163,7 @@ static constexpr const char *BOLDNESS_ATTR = "boldness";
|
||||
static constexpr const char *SKEW_ATTR = "skew";
|
||||
static constexpr const char *DISTANCE_ATTR = "distance";
|
||||
static constexpr const char *ANGLE_ATTR = "angle";
|
||||
static constexpr const char *COLLECTION_NUMBER_ATTR = "collection";
|
||||
|
||||
static constexpr const char *FONT_FAMILY_ATTR = "family";
|
||||
static constexpr const char *FONT_FACE_NAME_ATTR = "face_name";
|
||||
@ -3329,7 +3330,8 @@ void TextConfigurationSerialization::to_xml(std::stringstream &stream, const Tex
|
||||
stream << DISTANCE_ATTR << "=\"" << *fp.distance << "\" ";
|
||||
if (fp.angle.has_value())
|
||||
stream << ANGLE_ATTR << "=\"" << *fp.angle << "\" ";
|
||||
|
||||
if (fp.collection_number.has_value())
|
||||
stream << COLLECTION_NUMBER_ATTR << "=\"" << *fp.collection_number << "\" ";
|
||||
// font descriptor
|
||||
if (fp.family.has_value())
|
||||
stream << FONT_FAMILY_ATTR << "=\"" << *fp.family << "\" ";
|
||||
@ -3361,6 +3363,8 @@ std::optional<TextConfiguration> TextConfigurationSerialization::read(const char
|
||||
float angle = get_attribute_value_float(attributes, num_attributes, ANGLE_ATTR);
|
||||
if (std::fabs(angle) > std::numeric_limits<float>::epsilon())
|
||||
fp.angle = angle;
|
||||
int collection_number = get_attribute_value_int(attributes, num_attributes, COLLECTION_NUMBER_ATTR);
|
||||
if (collection_number > 0) fp.collection_number = collection_number;
|
||||
|
||||
fp.size_in_mm = get_attribute_value_float(attributes, num_attributes, LINE_HEIGHT_ATTR);
|
||||
fp.emboss = get_attribute_value_float(attributes, num_attributes, DEPTH_ATTR);
|
||||
|
@ -43,6 +43,10 @@ struct FontProp
|
||||
// When not set value is zero and is not stored
|
||||
std::optional<float> angle; // [in radians]
|
||||
|
||||
// Parameter for True Type Font collections
|
||||
// Select index of font in collection
|
||||
std::optional<int> collection_number;
|
||||
|
||||
//enum class Align {
|
||||
// left,
|
||||
// right,
|
||||
|
@ -78,7 +78,7 @@ GLGizmoEmboss::GLGizmoEmboss(GLCanvas3D &parent)
|
||||
|
||||
void GLGizmoEmboss::set_fine_position()
|
||||
{
|
||||
const Selection & selection = m_parent.get_selection();
|
||||
const Selection &selection = m_parent.get_selection();
|
||||
const Selection::IndicesList indices = selection.get_volume_idxs();
|
||||
// no selected volume
|
||||
if (indices.empty()) return;
|
||||
@ -157,7 +157,7 @@ void GLGizmoEmboss::create_volume(ModelVolumeType volume_type, const Vec2d& mous
|
||||
Plater* plater = wxGetApp().plater();
|
||||
const Camera &camera = plater->get_camera();
|
||||
auto data = std::make_unique<EmbossDataCreate>(
|
||||
m_font_manager.get_font_file(),
|
||||
m_font_manager.get_font().font_file_with_cache,
|
||||
create_configuration(),
|
||||
create_volume_name(), volume_type, screen_coor, object_idx,
|
||||
hit_vol_tr, camera,
|
||||
@ -662,9 +662,9 @@ bool GLGizmoEmboss::process()
|
||||
if (m_volume == nullptr) return false;
|
||||
|
||||
// exist loaded font?
|
||||
std::shared_ptr<Emboss::FontFile>& font_file = m_font_manager.get_font_file();
|
||||
if (font_file == nullptr) return false;
|
||||
auto data = std::make_unique<EmbossDataUpdate>(font_file,
|
||||
Emboss::FontFileWithCache font = m_font_manager.get_font().font_file_with_cache;
|
||||
if (!font.has_value()) return false;
|
||||
auto data = std::make_unique<EmbossDataUpdate>(font,
|
||||
create_configuration(),
|
||||
create_volume_name(), m_volume);
|
||||
|
||||
@ -1401,6 +1401,7 @@ void GLGizmoEmboss::draw_style_edit() {
|
||||
|
||||
if (exist_change) {
|
||||
m_font_manager.free_style_images();
|
||||
m_font_manager.clear_glyphs_cache();
|
||||
process();
|
||||
}
|
||||
|
||||
@ -1581,21 +1582,27 @@ void GLGizmoEmboss::draw_advanced()
|
||||
ImGui::Text("%s", _u8L("Advanced font options could be change only for corect font.\nStart with select correct font.").c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
FontProp &font_prop = m_font_manager.get_font_item().prop;
|
||||
|
||||
#ifdef SHOW_FONT_FILE_PROPERTY
|
||||
ImGui::SameLine();
|
||||
auto& ff = m_font_manager.get_font().font_file_with_cache;
|
||||
int cache_size = ff.has_value()? (int)ff.cache->size() : 0;
|
||||
std::string ff_property =
|
||||
"ascent=" + std::to_string(font_file->ascent) +
|
||||
", descent=" + std::to_string(font_file->descent) +
|
||||
", lineGap=" + std::to_string(font_file->linegap) +
|
||||
", unitPerEm=" + std::to_string(font_file->unit_per_em) +
|
||||
", cache(" + std::to_string(font_file->cache.size()) + " glyphs)";
|
||||
if (font_file->count > 1) ff_property +=
|
||||
", collect=" + std::to_string(font_file->index + 1) + "/" + std::to_string(font_file->count);
|
||||
", unitPerEm=" + std::to_string(font_file->unit_per_em) +
|
||||
", cache(" + std::to_string(cache_size) + " glyphs)";
|
||||
if (font_file->count > 1) {
|
||||
int collection = font_prop.collection_number.has_value() ?
|
||||
*font_prop.collection_number : 0;
|
||||
ff_property += ", collect=" + std::to_string(collection+1) + "/" + std::to_string(font_file->count);
|
||||
}
|
||||
m_imgui->text_colored(ImGuiWrapper::COL_GREY_DARK, ff_property);
|
||||
#endif // SHOW_FONT_FILE_PROPERTY
|
||||
|
||||
FontProp &font_prop = m_font_manager.get_font_item().prop;
|
||||
bool exist_change = false;
|
||||
|
||||
auto &tr = m_gui_cfg->translations;
|
||||
@ -1693,12 +1700,15 @@ void GLGizmoEmboss::draw_advanced()
|
||||
ImGui::Text("%s", tr.collection.c_str());
|
||||
ImGui::SameLine(m_gui_cfg->advanced_input_offset);
|
||||
ImGui::SetNextItemWidth(m_gui_cfg->advanced_input_width);
|
||||
if (ImGui::BeginCombo("## Font collection", std::to_string(font_file->index).c_str())) {
|
||||
unsigned int selected = font_prop.collection_number.has_value() ?
|
||||
*font_prop.collection_number : 0;
|
||||
if (ImGui::BeginCombo("## Font collection", std::to_string(selected).c_str())) {
|
||||
for (unsigned int i = 0; i < font_file->count; ++i) {
|
||||
ImGui::PushID(1 << (10 + i));
|
||||
bool is_selected = i == font_file->index;
|
||||
bool is_selected = (i == selected);
|
||||
if (ImGui::Selectable(std::to_string(i).c_str(), is_selected)) {
|
||||
font_file->index = i;
|
||||
if (i == 0) font_prop.collection_number.reset();
|
||||
else font_prop.collection_number = i;
|
||||
exist_change = true;
|
||||
}
|
||||
ImGui::PopID();
|
||||
@ -1711,6 +1721,7 @@ void GLGizmoEmboss::draw_advanced()
|
||||
|
||||
if (exist_change) {
|
||||
m_font_manager.free_style_images();
|
||||
m_font_manager.clear_glyphs_cache();
|
||||
process();
|
||||
}
|
||||
#ifdef ALLOW_DEBUG_MODE
|
||||
|
@ -22,11 +22,11 @@ using namespace GUI;
|
||||
void EmbossUpdateJob::process(Ctl &ctl)
|
||||
{
|
||||
// check if exist valid font
|
||||
if (m_input->font_file == nullptr) return;
|
||||
if (!m_input->font_file.has_value()) return;
|
||||
|
||||
const TextConfiguration &cfg = m_input->text_configuration;
|
||||
m_result = EmbossCreateJob::create_mesh(
|
||||
cfg.text.c_str(), *m_input->font_file, cfg.font_item.prop, ctl);
|
||||
cfg.text.c_str(), m_input->font_file, cfg.font_item.prop, ctl);
|
||||
if (m_result.its.empty()) return;
|
||||
if (ctl.was_canceled()) return;
|
||||
|
||||
@ -98,11 +98,11 @@ void EmbossUpdateJob::finalize(bool canceled, std::exception_ptr &)
|
||||
void EmbossCreateJob::process(Ctl &ctl) {
|
||||
// It is neccessary to create some shape
|
||||
// Emboss text window is opened by creation new emboss text object
|
||||
m_result = (m_input->font_file == nullptr) ?
|
||||
create_default_mesh() :
|
||||
create_mesh(m_input->text_configuration.text.c_str(),
|
||||
*m_input->font_file,
|
||||
m_input->text_configuration.font_item.prop, ctl);
|
||||
const char *text = m_input->text_configuration.text.c_str();
|
||||
FontProp &prop = m_input->text_configuration.font_item.prop;
|
||||
m_result = (m_input->font_file.has_value()) ?
|
||||
create_mesh(text, m_input->font_file, prop, ctl):
|
||||
create_default_mesh();
|
||||
if (m_result.its.empty()) m_result = create_default_mesh();
|
||||
if (ctl.was_canceled()) return;
|
||||
|
||||
@ -240,16 +240,20 @@ TriangleMesh EmbossCreateJob::create_default_mesh()
|
||||
return triangle_mesh;
|
||||
}
|
||||
|
||||
TriangleMesh EmbossCreateJob::create_mesh(const char * text,
|
||||
Emboss::FontFile &font,
|
||||
const FontProp & font_prop,
|
||||
Ctl & ctl)
|
||||
TriangleMesh EmbossCreateJob::create_mesh(const char *text,
|
||||
Emboss::FontFileWithCache &font,
|
||||
const FontProp &font_prop,
|
||||
Ctl &ctl)
|
||||
{
|
||||
assert(font.has_value());
|
||||
if (!font.has_value()) return {};
|
||||
|
||||
ExPolygons shapes = Emboss::text2shapes(font, text, font_prop);
|
||||
if (shapes.empty()) return {};
|
||||
if (ctl.was_canceled()) return {};
|
||||
|
||||
float scale = font_prop.size_in_mm / font.unit_per_em;
|
||||
int unit_per_em = font.font_file->unit_per_em;
|
||||
float scale = font_prop.size_in_mm / unit_per_em;
|
||||
float depth = font_prop.emboss / scale;
|
||||
auto projectZ = std::make_unique<Emboss::ProjectZ>(depth);
|
||||
Emboss::ProjectScale project(std::move(projectZ), scale);
|
||||
|
@ -47,7 +47,7 @@ public:
|
||||
/// <param name="ctl">Control for job, check of cancelation</param>
|
||||
/// <returns>Triangle mesh model</returns>
|
||||
static TriangleMesh create_mesh(const char * text,
|
||||
Emboss::FontFile &font,
|
||||
Emboss::FontFileWithCache &font,
|
||||
const FontProp & font_prop,
|
||||
Ctl & ctl);
|
||||
|
||||
@ -61,16 +61,16 @@ private:
|
||||
/// </summary>
|
||||
struct EmbossDataBase
|
||||
{
|
||||
// Pointer on Data of font (glyph shapes)
|
||||
std::shared_ptr<Emboss::FontFile> font_file;
|
||||
// Keep pointer on Data of font (glyph shapes)
|
||||
Emboss::FontFileWithCache font_file;
|
||||
// font item is not used for create object
|
||||
TextConfiguration text_configuration;
|
||||
// new volume name created from text
|
||||
std::string volume_name;
|
||||
EmbossDataBase(std::shared_ptr<Emboss::FontFile> font_file,
|
||||
TextConfiguration text_configuration,
|
||||
std::string volume_name)
|
||||
: font_file(std::move(font_file))
|
||||
EmbossDataBase(Emboss::FontFileWithCache font_file,
|
||||
TextConfiguration text_configuration,
|
||||
std::string volume_name)
|
||||
: font_file(font_file)
|
||||
, text_configuration(text_configuration)
|
||||
, volume_name(volume_name)
|
||||
{}
|
||||
@ -88,11 +88,11 @@ struct EmbossDataUpdate : public EmbossDataBase
|
||||
// unique identifier of volume to change
|
||||
// Change of volume change id, last change could disapear
|
||||
// ObjectID volume_id;
|
||||
EmbossDataUpdate(std::shared_ptr<Emboss::FontFile> font_file,
|
||||
TextConfiguration text_configuration,
|
||||
std::string volume_name,
|
||||
ModelVolume * volume)
|
||||
: EmbossDataBase(std::move(font_file), text_configuration, volume_name)
|
||||
EmbossDataUpdate(Emboss::FontFileWithCache font_file,
|
||||
TextConfiguration text_configuration,
|
||||
std::string volume_name,
|
||||
ModelVolume *volume)
|
||||
: EmbossDataBase(font_file, text_configuration, volume_name)
|
||||
, volume(volume)
|
||||
{}
|
||||
};
|
||||
@ -125,7 +125,7 @@ struct EmbossDataCreate: public EmbossDataBase
|
||||
// It is inside of GLGizmoEmboss object,
|
||||
// so I hope it will survive
|
||||
|
||||
EmbossDataCreate(std::shared_ptr<Emboss::FontFile> font_file,
|
||||
EmbossDataCreate(Emboss::FontFileWithCache font_file,
|
||||
const TextConfiguration & text_configuration,
|
||||
const std::string & volume_name,
|
||||
ModelVolumeType volume_type,
|
||||
@ -135,7 +135,7 @@ struct EmbossDataCreate: public EmbossDataBase
|
||||
const Camera& camera,
|
||||
const std::vector<Vec2d> & bed_shape,
|
||||
RaycastManager * raycast_manager)
|
||||
: EmbossDataBase(std::move(font_file), text_configuration, volume_name)
|
||||
: EmbossDataBase(font_file, text_configuration, volume_name)
|
||||
, volume_type(volume_type)
|
||||
, screen_coor(screen_coor)
|
||||
, object_idx(object_idx)
|
||||
|
@ -14,6 +14,7 @@ const std::string FontListSerializable::APP_CONFIG_FONT_BOLDNESS = "boldness"
|
||||
const std::string FontListSerializable::APP_CONFIG_FONT_SKEW = "skew";
|
||||
const std::string FontListSerializable::APP_CONFIG_FONT_DISTANCE = "distance";
|
||||
const std::string FontListSerializable::APP_CONFIG_FONT_ANGLE = "angle";
|
||||
const std::string FontListSerializable::APP_CONFIG_FONT_COLLECTION = "collection";
|
||||
const std::string FontListSerializable::APP_CONFIG_FONT_CHAR_GAP = "char_gap";
|
||||
const std::string FontListSerializable::APP_CONFIG_FONT_LINE_GAP = "line_gap";
|
||||
|
||||
@ -83,6 +84,7 @@ std::optional<FontItem> FontListSerializable::load_font_item(
|
||||
read(app_cfg_section, APP_CONFIG_FONT_SKEW, fp.skew);
|
||||
read(app_cfg_section, APP_CONFIG_FONT_DISTANCE, fp.distance);
|
||||
read(app_cfg_section, APP_CONFIG_FONT_ANGLE, fp.angle);
|
||||
read(app_cfg_section, APP_CONFIG_FONT_COLLECTION, fp.collection_number);
|
||||
read(app_cfg_section, APP_CONFIG_FONT_CHAR_GAP, fp.char_gap);
|
||||
read(app_cfg_section, APP_CONFIG_FONT_LINE_GAP, fp.line_gap);
|
||||
|
||||
@ -109,6 +111,8 @@ void FontListSerializable::store_font_item(AppConfig & cfg,
|
||||
cfg.set(section_name, APP_CONFIG_FONT_DISTANCE, std::to_string(*fp.distance));
|
||||
if (fp.angle.has_value())
|
||||
cfg.set(section_name, APP_CONFIG_FONT_ANGLE, std::to_string(*fp.angle));
|
||||
if (fp.collection_number.has_value())
|
||||
cfg.set(section_name, APP_CONFIG_FONT_COLLECTION, std::to_string(*fp.collection_number));
|
||||
if (fp.char_gap.has_value())
|
||||
cfg.set(section_name, APP_CONFIG_FONT_CHAR_GAP, std::to_string(*fp.char_gap));
|
||||
if (fp.line_gap.has_value())
|
||||
|
@ -25,6 +25,7 @@ class FontListSerializable
|
||||
static const std::string APP_CONFIG_FONT_SKEW;
|
||||
static const std::string APP_CONFIG_FONT_DISTANCE;
|
||||
static const std::string APP_CONFIG_FONT_ANGLE;
|
||||
static const std::string APP_CONFIG_FONT_COLLECTION;
|
||||
static const std::string APP_CONFIG_FONT_CHAR_GAP;
|
||||
static const std::string APP_CONFIG_FONT_LINE_GAP;
|
||||
public:
|
||||
|
@ -72,13 +72,12 @@ bool FontManager::wx_font_changed(std::unique_ptr<Emboss::FontFile> font_file)
|
||||
if (!wx_font.has_value()) return false;
|
||||
|
||||
if (font_file == nullptr) {
|
||||
auto new_font_file = WxFontUtils::create_font_file(*wx_font);
|
||||
if (new_font_file == nullptr) return false;
|
||||
m_font_list[m_font_selected].font_file = std::move(new_font_file);
|
||||
} else {
|
||||
m_font_list[m_font_selected].font_file = std::move(font_file);
|
||||
font_file = WxFontUtils::create_font_file(*wx_font);
|
||||
if (font_file == nullptr) return false;
|
||||
}
|
||||
|
||||
m_font_list[m_font_selected].font_file_with_cache =
|
||||
Emboss::FontFileWithCache(std::move(font_file));
|
||||
|
||||
auto &fi = get_font_item();
|
||||
fi.type = WxFontUtils::get_actual_type();
|
||||
fi.path = WxFontUtils::store_wxFont(*wx_font);
|
||||
@ -150,7 +149,7 @@ std::shared_ptr<Emboss::FontFile> &FontManager::get_font_file()
|
||||
{
|
||||
// TODO: fix not selected font
|
||||
//if (!is_activ_font()) return nullptr;
|
||||
return m_font_list[m_font_selected].font_file;
|
||||
return m_font_list[m_font_selected].font_file_with_cache.font_file;
|
||||
}
|
||||
|
||||
const FontItem &FontManager::get_font_item() const
|
||||
@ -209,8 +208,17 @@ const std::optional<wxFont> &FontManager::get_wx_font() const
|
||||
return m_font_list[m_font_selected].wx_font;
|
||||
}
|
||||
|
||||
void FontManager::clear_glyphs_cache()
|
||||
{
|
||||
if (!is_activ_font()) return;
|
||||
Emboss::FontFileWithCache &ff = m_font_list[m_font_selected].font_file_with_cache;
|
||||
if (!ff.has_value()) return;
|
||||
ff.cache = std::make_shared<Emboss::Glyphs>();
|
||||
}
|
||||
|
||||
void FontManager::clear_imgui_font() {
|
||||
// TODO: improove to clear only actual font
|
||||
if (!is_activ_font()) return;
|
||||
free_imgui_fonts();
|
||||
return;
|
||||
ImFont *imgui_font = get_imgui_font(m_font_selected);
|
||||
@ -255,7 +263,7 @@ void FontManager::free_except_active_font() {
|
||||
const Item &act_item = m_font_list[m_font_selected];
|
||||
for (auto &item : m_font_list) {
|
||||
if (&item == &act_item) continue; // keep alive actual font file
|
||||
item.font_file = nullptr;
|
||||
item.font_file_with_cache = {};
|
||||
}
|
||||
}
|
||||
|
||||
@ -301,10 +309,11 @@ bool FontManager::set_up_font_file(size_t item_index)
|
||||
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());
|
||||
std::unique_ptr<Emboss::FontFile> font_ptr =
|
||||
Emboss::create_font_file(fi.path.c_str());
|
||||
if (font_ptr == nullptr) return false;
|
||||
item.font_file = std::move(font_ptr);
|
||||
item.font_file_with_cache =
|
||||
Emboss::FontFileWithCache(std::move(font_ptr));
|
||||
return true;
|
||||
}
|
||||
if (fi.type != WxFontUtils::get_actual_type()) return false;
|
||||
@ -366,10 +375,12 @@ void FontManager::create_texture(size_t index, const std::string &text, GLuint&
|
||||
{
|
||||
if (index >= m_font_list.size()) return;
|
||||
Item &item = m_font_list[index];
|
||||
if (!item.font_file_with_cache.has_value() && !set_up_font_file(index))
|
||||
return;
|
||||
|
||||
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);
|
||||
ExPolygons shapes = Emboss::text2shapes(item.font_file_with_cache,
|
||||
text.c_str(), font_prop);
|
||||
|
||||
BoundingBox bb;
|
||||
for (ExPolygon &shape : shapes) bb.merge(BoundingBox(shape.contour.points));
|
||||
@ -415,13 +426,12 @@ void FontManager::init_style_images(int max_width) {
|
||||
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;
|
||||
if (!item.font_file_with_cache.has_value() && !set_up_font_file(index))
|
||||
continue;
|
||||
|
||||
ExPolygons &shapes = name_shapes[index];
|
||||
shapes = Emboss::text2shapes(*font_file, font_item.name.c_str(), font_prop);
|
||||
shapes = Emboss::text2shapes(item.font_file_with_cache, font_item.name.c_str(), font_prop);
|
||||
|
||||
// create image description
|
||||
item.image = StyleImage();
|
||||
@ -437,7 +447,8 @@ void FontManager::init_style_images(int max_width) {
|
||||
// dot per inch for monitor
|
||||
int dpi = get_dpi_for_window(mf);
|
||||
double ppm = dpi / 25.4; // pixel per milimeter
|
||||
double scale = font_prop.size_in_mm / font_file->unit_per_em * Emboss::SHAPE_SCALE * ppm;
|
||||
double unit_per_em = item.font_file_with_cache.font_file->unit_per_em;
|
||||
double scale = font_prop.size_in_mm / unit_per_em * Emboss::SHAPE_SCALE * ppm;
|
||||
scales[index] = scale;
|
||||
|
||||
//double scale = font_prop.size_in_mm * SCALING_FACTOR;
|
||||
@ -520,11 +531,6 @@ void FontManager::init_style_images(int max_width) {
|
||||
|
||||
void FontManager::free_style_images() {
|
||||
if (!is_activ_font()) return;
|
||||
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();
|
||||
@ -560,8 +566,8 @@ ImFont * FontManager::load_imgui_font(size_t index, const std::string &text)
|
||||
|
||||
if (index >= m_font_list.size()) return nullptr;
|
||||
Item &item = m_font_list[index];
|
||||
if (item.font_file == nullptr) return nullptr;
|
||||
const Emboss::FontFile &font_file = *item.font_file;
|
||||
if (!item.font_file_with_cache.has_value()) return nullptr;
|
||||
const Emboss::FontFile &font_file = *item.font_file_with_cache.font_file;
|
||||
|
||||
// TODO: Create glyph range
|
||||
ImFontGlyphRangesBuilder builder;
|
||||
@ -596,7 +602,7 @@ ImFont * FontManager::load_imgui_font(size_t index, const std::string &text)
|
||||
|
||||
font_config.FontDataOwnedByAtlas = false;
|
||||
|
||||
const std::vector<unsigned char> &buffer = font_file.buffer;
|
||||
const std::vector<unsigned char> &buffer = *font_file.data;
|
||||
m_imgui_font_atlas.AddFontFromMemoryTTF(
|
||||
(void *) buffer.data(), buffer.size(), font_size, &font_config, item.font_ranges.Data);
|
||||
|
||||
@ -633,9 +639,10 @@ bool FontManager::set_wx_font(size_t item_index, const wxFont &wx_font) {
|
||||
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;
|
||||
Item &item = m_font_list[item_index];
|
||||
item.font_file_with_cache =
|
||||
Emboss::FontFileWithCache(std::move(font_file));
|
||||
item.wx_font = wx_font;
|
||||
|
||||
FontItem &fi = item.font_item;
|
||||
fi.type = WxFontUtils::get_actual_type();
|
||||
|
@ -59,6 +59,9 @@ public:
|
||||
// fastering load font on index by wxFont, ignore type and descriptor
|
||||
bool load_font(size_t font_index, const wxFont &font);
|
||||
|
||||
// clear actual selected glyphs cache
|
||||
void clear_glyphs_cache();
|
||||
|
||||
// remove cached imgui font for actual selected font
|
||||
void clear_imgui_font();
|
||||
|
||||
@ -137,7 +140,7 @@ public:
|
||||
std::string truncated_name;
|
||||
|
||||
// share font file data with emboss job thread
|
||||
std::shared_ptr<Emboss::FontFile> font_file = nullptr;
|
||||
Emboss::FontFileWithCache font_file_with_cache;
|
||||
|
||||
std::optional<size_t> imgui_font_index;
|
||||
|
||||
|
@ -45,7 +45,7 @@ bool WxFontUtils::can_load(const wxFont &font)
|
||||
std::unique_ptr<Emboss::FontFile> WxFontUtils::create_font_file(const wxFont &font)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return Emboss::load_font(font.GetHFONT());
|
||||
return Emboss::create_font_file(font.GetHFONT());
|
||||
#elif defined(__APPLE__)
|
||||
// use file path
|
||||
const wxNativeFontInfo *info = font.GetNativeFontInfo();
|
||||
@ -61,12 +61,12 @@ std::unique_ptr<Emboss::FontFile> WxFontUtils::create_font_file(const wxFont &fo
|
||||
size_t start = std::string("file://").size();
|
||||
if (file_path.empty() || file_path.size() <= start) return nullptr;
|
||||
file_path = file_path.substr(start, file_path.size() - start);
|
||||
return Emboss::load_font(file_path.c_str());
|
||||
return Emboss::create_font_file(file_path.c_str());
|
||||
#elif defined(__linux__)
|
||||
static FontConfigHelp help;
|
||||
std::string font_path = help.get_font_path(font);
|
||||
if (font_path.empty()) return nullptr;
|
||||
return Emboss::load_font(font_path.c_str());
|
||||
return Emboss::create_font_file(font_path.c_str());
|
||||
#else
|
||||
// HERE is place to add implementation for another platform
|
||||
// to convert wxFont to font data as windows or font file path as linux
|
||||
|
@ -130,7 +130,7 @@ TEST_CASE("Emboss text", "[Emboss]")
|
||||
char letter = '%';
|
||||
float flatness = 2.;
|
||||
|
||||
auto font = Emboss::load_font(font_path.c_str());
|
||||
auto font = Emboss::create_font_file(font_path.c_str());
|
||||
REQUIRE(font != nullptr);
|
||||
|
||||
std::optional<Emboss::Glyph> glyph = Emboss::letter2glyph(*font, letter, flatness);
|
||||
@ -237,7 +237,7 @@ TEST_CASE("Italic check", "[]")
|
||||
[](unsigned char c) { return std::tolower(c); });
|
||||
if (ext != ".ttf") continue;
|
||||
std::string path_str = act_path.u8string();
|
||||
auto font_opt = Emboss::load_font(path_str.c_str());
|
||||
auto font_opt = Emboss::create_font_file(path_str.c_str());
|
||||
if (font_opt == nullptr) continue;
|
||||
if (Emboss::is_italic(*font_opt))
|
||||
exist_italic = true;
|
||||
|
Loading…
Reference in New Issue
Block a user