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