Different font type by OS

Connect size with wxFont
This commit is contained in:
Filip Sykala 2021-10-26 18:56:19 +02:00
parent ae5f594e1e
commit 706d963f7f
5 changed files with 238 additions and 118 deletions

View File

@ -134,7 +134,8 @@ std::optional<Emboss::Glyph> Private::get_glyph(
FontItem Private::create_font_item(std::wstring name, std::wstring path) {
return FontItem(boost::nowide::narrow(name.c_str()),
boost::nowide::narrow(path.c_str()));
boost::nowide::narrow(path.c_str()),
FontItem::Type::file_path);
}
ExPolygons Private::dilate_to_unique_points(ExPolygons &expolygons)

View File

@ -148,6 +148,7 @@ static constexpr const char *TEXT_TAG = "emboss";
static constexpr const char *TEXT_DATA_ATTR = "text";
// TextConfiguration::FontItem
static constexpr const char *FONT_DESCRIPTOR_ATTR = "font_descriptor";
static constexpr const char *FONT_DESCRIPTOR_TYPE_ATTR = "font_descriptor_type";
// TextConfiguration::FontProperty
static constexpr const char *CHAR_GAP_ATTR = "char_gap";
@ -1774,6 +1775,37 @@ namespace Slic3r {
return true;
}
struct TextConfigurationSerialization
{
public:
TextConfigurationSerialization() = delete;
static const std::map<FontItem::Type, std::string> to_string;
static const std::map<std::string, FontItem::Type> to_type;
static FontItem::Type get_type(const std::string &type_string) {
auto it = to_type.find(type_string);
return (it != to_type.end()) ? it->second : FontItem::Type::undefined;
}
static void to_xml(std::stringstream &stream, const TextConfiguration &tc);
static std::optional<TextConfiguration> read(const char **attributes, unsigned int num_attributes);
/// <summary>
/// Create map with swaped key-value
/// IMPROVE: Move to map utils
/// </summary>
/// <param name="map">Input map</param>
/// <returns>Map with swapped key-value</returns>
template<typename Key, typename Value>
static std::map<Value, Key> create_oposit_map(
const std::map<Key, Value> &map)
{
std::map<Value, Key> result;
for (const auto &it : map) result[it.second] = it.first;
return result;
}
};
bool _3MF_Importer::_handle_start_text_configuration(const char **attributes, unsigned int num_attributes)
{
IdToMetadataMap::iterator object = m_objects_metadata.find(m_curr_config.object_id);
@ -1786,22 +1818,8 @@ namespace Slic3r {
return false;
}
ObjectMetadata::VolumeMetadata& volume = object->second.volumes.back();
std::string text = get_attribute_value_string(attributes, num_attributes, TEXT_DATA_ATTR);
std::string font_name = "";
std::string font_descriptor = get_attribute_value_string(attributes, num_attributes, FONT_DESCRIPTOR_ATTR);
FontItem::Type font_type = FontItem::Type::loaded_from_3mf; // default font type
FontItem fi(font_name, font_descriptor, font_type);
FontProp fp;
fp.char_gap = get_attribute_value_int(attributes, num_attributes, CHAR_GAP_ATTR);
fp.line_gap = get_attribute_value_int(attributes, num_attributes, LINE_GAP_ATTR);
fp.flatness = get_attribute_value_float(attributes, num_attributes, FLATNESS_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);
volume.text_configuration = TextConfiguration(fi, fp, text);
return true;
volume.text_configuration = TextConfigurationSerialization::read(attributes, num_attributes);
return volume.text_configuration.has_value();
}
bool _3MF_Importer::_handle_end_text_configuration() {
@ -2233,6 +2251,7 @@ namespace Slic3r {
bool _add_print_config_file_to_archive(mz_zip_archive& archive, const DynamicPrintConfig &config);
bool _add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model, const IdToObjectDataMap &objects_data);
bool _add_custom_gcode_per_print_z_file_to_archive(mz_zip_archive& archive, Model& model, const DynamicPrintConfig* config);
void _add_text_configuration(std::stringstream& stream, const TextConfiguration& cfg);
};
bool _3MF_Exporter::save_model_to_file(const std::string& filename, Model& model, const DynamicPrintConfig* config, bool fullpath_sources, const ThumbnailData* thumbnail_data, bool zip64)
@ -3090,24 +3109,8 @@ namespace Slic3r {
}
// stores volume's text data
if (volume->text_configuration.has_value()) {
const TextConfiguration& tc = *volume->text_configuration;
stream << " <" << TEXT_TAG << " ";
stream << TEXT_DATA_ATTR << "=\"" << xml_escape(tc.text) << "\" ";
// font item
const auto &fi = tc.font_item;
stream << FONT_DESCRIPTOR_ATTR << "=\"" << fi.path << "\" ";
// font property
const auto &fp = tc.font_prop;
stream << CHAR_GAP_ATTR << "=\"" << fp.char_gap << "\" ";
stream << LINE_GAP_ATTR << "=\"" << fp.line_gap << "\" ";
stream << FLATNESS_ATTR << "=\"" << fp.flatness << "\" ";
stream << LINE_HEIGHT_ATTR << "=\"" << fp.size_in_mm << "\" ";
stream << DEPTH_ATTR << "=\"" << fp.emboss << "\" ";
stream << "/>\n"; // end TEXT_TAG
}
if (volume->text_configuration.has_value())
_add_text_configuration(stream, *volume->text_configuration);
// stores mesh's statistics
const RepairedMeshErrors& stats = volume->mesh().stats().repaired_errors;
@ -3188,6 +3191,12 @@ bool _3MF_Exporter::_add_custom_gcode_per_print_z_file_to_archive( mz_zip_archiv
return true;
}
void _3MF_Exporter::_add_text_configuration(std::stringstream & stream,
const TextConfiguration &tc)
{
TextConfigurationSerialization::to_xml(stream, tc);
}
// Perform conversions based on the config values available.
//FIXME provide a version of PrusaSlicer that stored the project file (3MF).
static void handle_legacy_project_loaded(unsigned int version_project_file, DynamicPrintConfig& config)
@ -3230,4 +3239,59 @@ bool store_3mf(const char* path, Model* model, const DynamicPrintConfig* config,
return res;
}
/// <summary>
/// TextConfiguration serialization
/// </summary>
const std::map<FontItem::Type, std::string> TextConfigurationSerialization::to_string = {
{FontItem::Type::file_path, "file_name"},
{FontItem::Type::wx_win_font_descr, "wxFontDescriptor_Windows"},
{FontItem::Type::wx_lin_font_descr, "wxFontDescriptor_Linux"},
{FontItem::Type::wx_mac_font_descr, "wxFontDescriptor_MacOsX"}
};
const std::map<std::string, FontItem::Type> TextConfigurationSerialization::to_type =
TextConfigurationSerialization::create_oposit_map(TextConfigurationSerialization::to_string);
void TextConfigurationSerialization::to_xml(std::stringstream &stream, const TextConfiguration &tc)
{
stream << " <" << TEXT_TAG << " ";
stream << TEXT_DATA_ATTR << "=\"" << xml_escape(tc.text) << "\" ";
// font item
const FontItem &fi = tc.font_item;
stream << FONT_DESCRIPTOR_ATTR << "=\"" << fi.path << "\" ";
stream << FONT_DESCRIPTOR_TYPE_ATTR << "=\"" << TextConfigurationSerialization::to_string.at(fi.type) << "\" ";
// font property
const FontProp &fp = tc.font_prop;
stream << CHAR_GAP_ATTR << "=\"" << fp.char_gap << "\" ";
stream << LINE_GAP_ATTR << "=\"" << fp.line_gap << "\" ";
stream << FLATNESS_ATTR << "=\"" << fp.flatness << "\" ";
stream << LINE_HEIGHT_ATTR << "=\"" << fp.size_in_mm << "\" ";
stream << DEPTH_ATTR << "=\"" << fp.emboss << "\" ";
stream << "/>\n"; // end TEXT_TAG
}
std::optional<TextConfiguration> TextConfigurationSerialization::read(const char **attributes, unsigned int num_attributes)
{
std::string text = get_attribute_value_string(attributes, num_attributes, TEXT_DATA_ATTR);
std::string font_name = "";
std::string font_descriptor = get_attribute_value_string(attributes, num_attributes, FONT_DESCRIPTOR_ATTR);
std::string type_str = get_attribute_value_string(attributes, num_attributes, FONT_DESCRIPTOR_TYPE_ATTR);
FontItem::Type type = TextConfigurationSerialization::get_type(type_str);
FontItem fi(font_name, font_descriptor, type);
FontProp fp;
fp.char_gap = get_attribute_value_int(attributes, num_attributes, CHAR_GAP_ATTR);
fp.line_gap = get_attribute_value_int(attributes, num_attributes, LINE_GAP_ATTR);
fp.flatness = get_attribute_value_float(attributes, num_attributes, FLATNESS_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);
return TextConfiguration(fi, fp, text);
}
} // namespace Slic3r

View File

@ -3,8 +3,18 @@
#include <vector>
#include <string>
#include <optional>
namespace Slic3r {
// additional information stored/load to/from .3mf file
// to be platform independent
struct Font3mfDesc
{
std::string family;
Font3mfDesc() = default;
};
// represent selected font
// Name must be human readable is visible in gui
@ -16,17 +26,21 @@ struct FontItem
enum class Type;
Type type;
FontItem() : type(Type::undefined) {}
FontItem(const std::string &name, const std::string &path, Type type = Type::file_path)
std::optional<Font3mfDesc> font3mf; // description from 3mf
FontItem() : type(Type::undefined){} // set undefined type
FontItem(const std::string &name, const std::string &path, Type type)
: name(name), path(path), type(type)
{}
// way of load font described in path string
// define data stored in path
enum class Type {
undefined = 0,
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
loaded_from_3mf
file_path, // TrueTypeFont file loacation on computer - for privacy: path is NOT stored into 3mf
// wx font descriptors are platform dependent
wx_win_font_descr, // path is font descriptor generated by wxWidgets on windows
wx_lin_font_descr, // path is font descriptor generated by wxWidgets on windows
wx_mac_font_descr // path is font descriptor generated by wxWidgets on windows
};
};
using FontList = std::vector<FontItem>;
@ -65,7 +79,8 @@ struct TextConfiguration
const std::string &text)
: font_item(font_item), font_prop(font_prop), text(text)
{}
};
};
} // namespace Slic3r
#endif // slic3r_TextConfiguration_hpp_

View File

@ -25,27 +25,17 @@
#include <GL/glew.h>
#ifdef __APPLE__
#ifdef _WIN32
// no specific include
#elif defined(__APPLE__)
#include <wx/uri.h>
#include <CoreText/CTFont.h>
#include <wx/osx/core/cfdictionary.h>
#define USE_FONT_DIALOG
#endif // apple
#ifdef __linux__
//#ifdef __WXGTK__
#define FontConfigExist
#endif
#ifdef FontConfigExist
#else // #ifdef __linux__
// Font Config must exist
#include <wx/filename.h>
#include <fontconfig/fontconfig.h>
#define USE_FONT_DIALOG
#endif // FontConfigExist
#ifdef _WIN32
#define USE_FONT_DIALOG
#endif // _WIN32
#endif
// uncomment for easier debug
// #define ALLOW_DEBUG_MODE
@ -61,6 +51,7 @@ public:
// Must be in gui because of wxWidget
static std::optional<Slic3r::Emboss::Font> load_font(FontItem &fi);
static FontItem::Type get_actual_type();
static FontItem get_font_item(const wxFont &font);
// load font used by Operating system as default GUI
@ -459,6 +450,13 @@ void GLGizmoEmboss::draw_window()
}
#endif // ALLOW_DEBUG_MODE
std::string descriptor = m_font_list[m_font_selected].path;
wxFont wx_font = WxFontUtils::load_wxFont(descriptor);
ImGui::Text(("actual descriptor is " + descriptor).c_str());
//wx_font.
if (!m_font.has_value()) {
ImGui::Text(_u8L("Warning: No font is selected. Select correct one.").c_str());
}
@ -587,6 +585,13 @@ void GLGizmoEmboss::draw_text_input()
void GLGizmoEmboss::draw_advanced() {
if (ImGui::InputFloat(_u8L("Size[in mm]").c_str(), &m_font_prop.size_in_mm)) {
if (m_font_prop.size_in_mm < 0.1) m_font_prop.size_in_mm = 10;
// store font size into path
FontItem& fi = m_font_list[m_font_selected];
if (fi.type == WxFontUtils::get_actual_type()) {
wxFont font = WxFontUtils::load_wxFont(fi.path);
font.SetPointSize(m_font_prop.size_in_mm);
fi.path = WxFontUtils::store_wxFont(font);
}
load_imgui_font();
process();
}
@ -782,7 +787,7 @@ bool GLGizmoEmboss::choose_font_by_wxdialog()
data.RestrictSelection(wxFONTRESTRICT_SCALABLE);
// set previous selected font
FontItem &selected_font_item = m_font_list[m_font_selected];
if (selected_font_item.type == FontItem::Type::wx_font_descr) {
if (selected_font_item.type == WxFontUtils::get_actual_type()) {
wxFont selected_font = WxFontUtils::load_wxFont(selected_font_item.path);
data.SetInitialFont(selected_font);
}
@ -836,7 +841,7 @@ bool GLGizmoEmboss::choose_true_type_file()
for (auto &input_file : input_files) {
std::string path = std::string(input_file.c_str());
std::string name = get_file_name(path);
m_font_list.emplace_back(name, path);
m_font_list.emplace_back(name, path, FontItem::Type::file_path);
// set first valid added font as active
if (!font_loaded) {
@ -881,14 +886,6 @@ bool GLGizmoEmboss::choose_svg_file()
return add_volume(name, its);
}
std::string GLGizmoEmboss::get_file_name(const std::string &file_path) {
size_t pos_last_delimiter = file_path.find_last_of('\\');
size_t pos_point = file_path.find_last_of('.');
size_t offset = pos_last_delimiter + 1;
size_t count = pos_point - pos_last_delimiter - 1;
return file_path.substr(offset, count);
}
TextConfiguration GLGizmoEmboss::create_configuration() {
return TextConfiguration(m_font_list[m_font_selected], m_font_prop, m_text);
}
@ -971,33 +968,6 @@ void GLGizmoEmboss::notify_cant_load_font(const FontItem &font_item) {
notification_manager->push_notification(type, level, text);
}
std::string GLGizmoEmboss::imgui_trunc(const std::string &text, float width)
{
static const char *tail = " ..";
float tail_width = ImGui::CalcTextSize(tail).x;
float text_width = ImGui::CalcTextSize(text.c_str()).x;
if (text_width < width) return text;
float letter_width = ImGui::CalcTextSize("n").x;
float allowed_width = width-tail_width;
unsigned count_letter = static_cast<unsigned>(allowed_width / letter_width);
text_width = ImGui::CalcTextSize(text.substr(0, count_letter).c_str()).x;
if (text_width < allowed_width) {
// increase letter count
do {
++count_letter;
text_width = ImGui::CalcTextSize(text.substr(0, count_letter).c_str()).x;
} while (text_width < allowed_width);
--count_letter;
} else {
// decrease letter count
do {
--count_letter;
text_width = ImGui::CalcTextSize(text.substr(0, count_letter).c_str()).x;
} while (text_width > allowed_width);
}
return text.substr(0, count_letter) + tail;
}
std::string GLGizmoEmboss::create_volume_name()
{
const size_t &max_len = m_gui_cfg->max_count_char_in_volume_name;
@ -1113,8 +1083,11 @@ void GLGizmoEmboss::store_font_list()
{
AppConfig *cfg = wxGetApp().app_config;
unsigned index = 1;
for (const FontItem &fi : m_font_list)
for (const FontItem &fi : m_font_list) {
// skip file paths + fonts from other OS
if (fi.type != WxFontUtils::get_actual_type()) continue;
set_font_item(*cfg, fi, index++);
}
// remove rest of font sections
std::string section_name = get_app_config_font_section(index);
@ -1143,7 +1116,7 @@ std::optional<FontItem> GLGizmoEmboss::get_font_item(
static const std::string default_name = "font_name";
const std::string& name = (name_it == app_cfg_section.end()) ?
default_name : name_it->second;
return FontItem(name, path, FontItem::Type::wx_font_descr);
return FontItem(name, path, WxFontUtils::get_actual_type());
}
void GLGizmoEmboss::set_font_item(AppConfig &cfg, const FontItem &fi, unsigned index) {
@ -1153,20 +1126,73 @@ void GLGizmoEmboss::set_font_item(AppConfig &cfg, const FontItem &fi, unsigned i
cfg.set(section_name, APP_CONFIG_FONT_DESCRIPTOR, fi.path);
}
std::string GLGizmoEmboss::get_file_name(const std::string &file_path)
{
size_t pos_last_delimiter = file_path.find_last_of('\\');
size_t pos_point = file_path.find_last_of('.');
size_t offset = pos_last_delimiter + 1;
size_t count = pos_point - pos_last_delimiter - 1;
return file_path.substr(offset, count);
}
std::string GLGizmoEmboss::imgui_trunc(const std::string &text, float width)
{
static const char *tail = " ..";
float tail_width = ImGui::CalcTextSize(tail).x;
float text_width = ImGui::CalcTextSize(text.c_str()).x;
if (text_width < width) return text;
float letter_width = ImGui::CalcTextSize("n").x;
float allowed_width = width - tail_width;
unsigned count_letter = static_cast<unsigned>(allowed_width /
letter_width);
text_width = ImGui::CalcTextSize(text.substr(0, count_letter).c_str()).x;
if (text_width < allowed_width) {
// increase letter count
do {
++count_letter;
text_width =
ImGui::CalcTextSize(text.substr(0, count_letter).c_str()).x;
} while (text_width < allowed_width);
--count_letter;
} else {
// decrease letter count
do {
--count_letter;
text_width =
ImGui::CalcTextSize(text.substr(0, count_letter).c_str()).x;
} while (text_width > allowed_width);
}
return text.substr(0, count_letter) + tail;
}
/// <summary>
/// WxFontUtils - Start definition
/// </summary>
std::optional<Emboss::Font> WxFontUtils::load_font(FontItem &fi)
{
switch (fi.type) {
case FontItem::Type::file_path:
return Emboss::load_font(fi.path.c_str());
case FontItem::Type::wx_font_descr:
return WxFontUtils::load_font(WxFontUtils::load_wxFont(fi.path));
case FontItem::Type::loaded_from_3mf: {
wxFont font = WxFontUtils::load_wxFont(fi.path);
// fix name
fi.name = get_human_readable_name(font);
fi.type = FontItem::Type::wx_font_descr;
return WxFontUtils::load_font(font);
if (fi.type == get_actual_type()) {
wxFont font = load_wxFont(fi.path);
// fill font name after load from .3mf
if (fi.name.empty()) fi.name = get_human_readable_name(font);
return load_font(load_wxFont(fi.path));
}
if (fi.type == FontItem::Type::file_path) {
// fill font name after load from .3mf
if (fi.name.empty())
fi.name = Slic3r::GUI::GLGizmoEmboss::get_file_name(fi.path);
return Emboss::load_font(fi.path.c_str());
}
// TODO: How to get more info from source 3mf file?
switch (fi.type) {
case FontItem::Type::wx_lin_font_descr:
case FontItem::Type::wx_win_font_descr:
case FontItem::Type::file_path:
case FontItem::Type::undefined:
default:
return {};
@ -1201,16 +1227,29 @@ std::optional<Emboss::Font> WxFontUtils::load_font(const wxFont &font)
#else
// HERE is place to add implementation for another platform
// to convert wxFont to font data as windows or font file path as linux
// Do not forget to allow macro USE_FONT_DIALOG
return {};
#endif
}
FontItem::Type WxFontUtils::get_actual_type() {
#ifdef _WIN32
return FontItem::Type::wx_win_font_descr;
#elif __APPLE__
return FontItem::Type::wx_mac_font_descr;
#elif defined(FontConfigExist)
return FontItem::Type::wx_mac_font_descr;
#else
return FontItem::Type::undefined;
#endif
}
FontItem WxFontUtils::get_font_item(const wxFont &font)
{
std::string name = get_human_readable_name(font);
std::string fontDesc = store_wxFont(font);
return FontItem(name, fontDesc, FontItem::Type::wx_font_descr);
std::string name = get_human_readable_name(font);
std::string fontDesc = store_wxFont(font);
FontItem::Type type = get_actual_type();
//wxFont f = font; // copy
return FontItem(name, fontDesc, type);
}
FontItem WxFontUtils::get_os_font()

View File

@ -66,9 +66,6 @@ private:
bool choose_true_type_file();
bool choose_svg_file();
// TODO: move to file utils
static std::string get_file_name(const std::string &file_path);
// Create object described how to make a Volume
TextConfiguration create_configuration();
bool load_configuration(ModelVolume *volume);
@ -77,9 +74,6 @@ private:
bool notify_unknown_font_type(ModelVolume *volume);
void notify_cant_load_font(const FontItem &font_item);
// TODO: Move to imgui utils
std::string imgui_trunc(const std::string &text, float width);
std::string create_volume_name();
// This configs holds GUI layout size given by translated texts.
@ -151,6 +145,13 @@ private:
// only temporary solution
static const std::string M_ICON_FILENAME;
public:
// TODO: move to file utils
static std::string get_file_name(const std::string &file_path);
// TODO: Move to imgui utils
std::string imgui_trunc(const std::string &text, float width);
};
} // namespace Slic3r::GUI