From d036c92a3793e8c0c758432b52f2af8ffeff751f Mon Sep 17 00:00:00 2001 From: "xin.zhang" Date: Wed, 19 Feb 2025 18:25:14 +0800 Subject: [PATCH] FIX: get suitable font size to draw the texts jira: [STUDIO-10067] Change-Id: I589fd6a271ae177e4630e403b64c18090aab9471 --- src/slic3r/CMakeLists.txt | 2 + src/slic3r/GUI/SelectMachinePop.cpp | 4 + src/slic3r/GUI/Widgets/AMSItem.cpp | 31 +- src/slic3r/GUI/Widgets/SwitchButton.cpp | 8 +- src/slic3r/Utils/WxFontUtils.cpp | 386 ++++++++++++++++++++++++ src/slic3r/Utils/WxFontUtils.hpp | 74 +++++ 6 files changed, 490 insertions(+), 15 deletions(-) create mode 100644 src/slic3r/Utils/WxFontUtils.cpp create mode 100644 src/slic3r/Utils/WxFontUtils.hpp diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index 017b2e11c..34a42896d 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -550,6 +550,8 @@ set(SLIC3R_GUI_SOURCES Utils/FontConfigHelp.hpp Utils/FontUtils.cpp Utils/FontUtils.hpp + Utils/WxFontUtils.hpp + Utils/WxFontUtils.cpp ) add_subdirectory(GUI/DeviceTab) diff --git a/src/slic3r/GUI/SelectMachinePop.cpp b/src/slic3r/GUI/SelectMachinePop.cpp index b5e050559..2f6f1681c 100644 --- a/src/slic3r/GUI/SelectMachinePop.cpp +++ b/src/slic3r/GUI/SelectMachinePop.cpp @@ -3,6 +3,9 @@ #include "libslic3r/Utils.hpp" #include "libslic3r/Thread.hpp" + +#include "slic3r/Utils/WxFontUtils.hpp" + #include "GUI.hpp" #include "GUI_App.hpp" #include "GUI_Preview.hpp" @@ -1027,6 +1030,7 @@ PinCodePanel::PinCodePanel(wxWindow* parent, int type, wxWindowID winid /*= wxID if (m_type == 0) {txt = _L("Bind with Pin Code");} else if (m_type == 1) {txt = _L("Bind with Access Code");} + WxFontUtils::get_suitable_font_size(0.5 * size.GetHeight(), dc); auto txt_size = dc.GetTextExtent(txt); dc.DrawText(txt, wxPoint(FromDIP(28), (size.y - txt_size.y) / 2)); diff --git a/src/slic3r/GUI/Widgets/AMSItem.cpp b/src/slic3r/GUI/Widgets/AMSItem.cpp index 66b23554f..92ce182a5 100644 --- a/src/slic3r/GUI/Widgets/AMSItem.cpp +++ b/src/slic3r/GUI/Widgets/AMSItem.cpp @@ -3,6 +3,7 @@ #include "../BitmapCache.hpp" #include "../I18N.hpp" #include "../GUI_App.hpp" +#include "../Utils/WxFontUtils.hpp" #include #include @@ -229,9 +230,11 @@ void AMSExtText::doRender(wxDC& dc) auto size = GetSize(); dc.SetPen(wxPen(StateColor::darkModeColorFor(AMS_CONTROL_GRAY800), 2, wxPENSTYLE_SOLID)); - auto tsize = dc.GetMultiLineTextExtent(_L("Ext")); - dc.SetFont(Label::Body_13); dc.SetTextForeground(StateColor::darkModeColorFor(AMS_CONTROL_GRAY800)); + dc.SetFont(Label::Body_13); + WxFontUtils::get_suitable_font_size(0.7 * size.GetHeight(), dc); + + auto tsize = dc.GetMultiLineTextExtent(_L("Ext")); wxPoint pot(FromDIP((size.x - tsize.x) / 2), FromDIP((size.y - tsize.y) / 2)); dc.DrawText(_L("Ext"), pot); } @@ -2873,24 +2876,28 @@ void AMSHumidity::doRender(wxDC& dc) pot = wxPoint(FromDIP(5), ((size.y - hum_img.GetBmpSize().y) / 2)); dc.DrawBitmap(hum_img.bmp(), pot); + pot.x += hum_img.GetBmpSize().x + FromDIP(3); // percentage wxString hum_percentage(std::to_string(m_amsinfo.humidity_raw)); - auto tsize = dc.GetMultiLineTextExtent(hum_percentage); dc.SetPen(wxPen(*wxTRANSPARENT_PEN)); dc.SetFont(Label::Body_14); dc.SetTextForeground(StateColor::darkModeColorFor(AMS_CONTROL_BLACK_COLOUR)); - // pot = wxPoint(FromDIP(size.x * 0.3), FromDIP((size.y - tsize.y) / 2)); - pot.x = pot.x + hum_img.GetBmpSize().x + FromDIP(3); - dc.DrawText(hum_percentage, pot); - pot.x += (tsize.x + FromDIP(5)); + WxFontUtils::get_suitable_font_size(0.7 * size.GetHeight(), dc); + auto tsize1 = dc.GetMultiLineTextExtent(hum_percentage); + pot.y = (size.y - tsize1.y) / 2; + dc.DrawText(hum_percentage, pot); + pot.x += (tsize1.x + FromDIP(3)); + + // percentage sign dc.SetFont(Label::Body_12); - tsize = dc.GetMultiLineTextExtent(_L("%")); - pot.y += (tsize.y / 2 - FromDIP(4)); + WxFontUtils::get_suitable_font_size(0.5 * size.GetHeight(), dc); + auto tsize2 = dc.GetMultiLineTextExtent(_L("%")); + pot.y = pot.y + ((tsize1.y - tsize2.y) / 2) + FromDIP(2); dc.DrawText(_L("%"), pot); - pot.x = pot.x + tsize.x + FromDIP(2); + pot.x += tsize2.x + FromDIP(3); } else /*image with number*/ { @@ -2916,8 +2923,8 @@ void AMSHumidity::doRender(wxDC& dc) //sun image /*pot.x = FromDIP(size.x * 0.69); pot.y = FromDIP((size.y - ams_sun_img.GetBmpHeight()) / 2);*/ - pot.x = pot.x + FromDIP(ams_sun_img.GetBmpWidth() / 2); - pot.y = FromDIP((size.y - ams_sun_img.GetBmpHeight()) / 2); + pot.x = pot.x + (ams_sun_img.GetBmpWidth() / 2); + pot.y = (size.y - ams_sun_img.GetBmpHeight()) / 2; dc.SetPen(wxPen(*wxTRANSPARENT_PEN)); dc.DrawBitmap(ams_sun_img.bmp(), pot); diff --git a/src/slic3r/GUI/Widgets/SwitchButton.cpp b/src/slic3r/GUI/Widgets/SwitchButton.cpp index 3528a5dd5..e697bd354 100644 --- a/src/slic3r/GUI/Widgets/SwitchButton.cpp +++ b/src/slic3r/GUI/Widgets/SwitchButton.cpp @@ -4,6 +4,7 @@ #include "../wxExtensions.hpp" #include "../Utils/MacDarkMode.hpp" +#include "../Utils/WxFontUtils.hpp" #include #include @@ -239,14 +240,16 @@ void SwitchBoard::doRender(wxDC &dc) dc.DrawRoundedRectangle(0, 0, GetSize().x / 2, GetSize().y, 8); } - auto left_txt_size = dc.GetTextExtent(leftLabel); - dc.SetFont(::Label::Body_13); if (switch_left) { dc.SetTextForeground(*wxWHITE); } else { dc.SetTextForeground(0x333333); } + dc.SetFont(::Label::Body_13); + Slic3r::GUI::WxFontUtils::get_suitable_font_size(0.6 * GetSize().GetHeight(), dc); + + auto left_txt_size = dc.GetTextExtent(leftLabel); dc.DrawText(leftLabel, wxPoint((GetSize().x / 2 - left_txt_size.x) / 2, (GetSize().y - left_txt_size.y) / 2)); /*right*/ @@ -257,7 +260,6 @@ void SwitchBoard::doRender(wxDC &dc) } auto right_txt_size = dc.GetTextExtent(rightLabel); - dc.SetFont(::Label::Body_13); if (switch_right) { dc.SetTextForeground(*wxWHITE); } else { diff --git a/src/slic3r/Utils/WxFontUtils.cpp b/src/slic3r/Utils/WxFontUtils.cpp new file mode 100644 index 000000000..75581f4e7 --- /dev/null +++ b/src/slic3r/Utils/WxFontUtils.cpp @@ -0,0 +1,386 @@ +#include "WxFontUtils.hpp" +#include +#include +#include "libslic3r/Utils.hpp" + +#if defined(__APPLE__) +#include +#include +#include // wxNativeFontInfo +#include +#elif defined(__linux__) +#include "slic3r/Utils/FontConfigHelp.hpp" +#endif + +using namespace Slic3r; +using namespace Slic3r::GUI; + +#ifdef __APPLE__ +namespace { +bool is_valid_ttf(std::string_view file_path) +{ + if (file_path.empty()) return false; + auto const pos_point = file_path.find_last_of('.'); + if (pos_point == std::string_view::npos) return false; + + // use point only after last directory delimiter + auto const pos_directory_delimiter = file_path.find_last_of("/\\"); + if (pos_directory_delimiter != std::string_view::npos && + pos_point < pos_directory_delimiter) + return false; // point is before directory delimiter + + // check count of extension chars + size_t extension_size = file_path.size() - pos_point; + if (extension_size >= 5) return false; // a lot of symbols for extension + if (extension_size <= 1) return false; // few letters for extension + + std::string_view extension = file_path.substr(pos_point + 1, extension_size); + + // Because of MacOs - Courier, Geneva, Monaco + if (extension == std::string_view("dfont")) return false; + + return true; +} + +// get filepath from wxFont on Mac OsX +std::string get_file_path(const wxFont& font) { + const wxNativeFontInfo *info = font.GetNativeFontInfo(); + if (info == nullptr) return {}; + CTFontDescriptorRef descriptor = info->GetCTFontDescriptor(); + CFURLRef typeref = (CFURLRef)CTFontDescriptorCopyAttribute(descriptor, kCTFontURLAttribute); + if (typeref == NULL) return {}; + ScopeGuard sg([&typeref]() { CFRelease(typeref); }); + CFStringRef url = CFURLGetString(typeref); + if (url == NULL) return {}; + wxString file_uri(wxCFStringRef::AsString(url)); + wxURI uri(file_uri); + const wxString &path = uri.GetPath(); + wxString path_unescaped = wxURI::Unescape(path); + std::string path_str = path_unescaped.ToUTF8().data(); + BOOST_LOG_TRIVIAL(trace) << "input uri(" << file_uri.c_str() << ") convert to path(" << path.c_str() << ") string(" << path_str << ")."; + return path_str; +} +} // namespace +#endif // __APPLE__ + +bool WxFontUtils::can_load(const wxFont &font) +{ + + if (!font.IsOk()) return false; +#ifdef _WIN32 + return Emboss::can_load(font.GetHFONT()) != nullptr; +#elif defined(__APPLE__) + return true; + //return is_valid_ttf(get_file_path(font)); +#elif defined(__linux__) + return true; + // font config check file path take about 4000ms for chech them all + //std::string font_path = Slic3r::GUI::get_font_path(font); + //return !font_path.empty(); +#endif + return false; +} + +std::unique_ptr WxFontUtils::create_font_file(const wxFont &font) +{ +#ifdef _WIN32 + return Emboss::create_font_file(font.GetHFONT()); +#elif defined(__APPLE__) + std::string file_path = get_file_path(font); + if (!is_valid_ttf(file_path)) { + BOOST_LOG_TRIVIAL(error) << "Can not process font('" << get_human_readable_name(font) << "'), " + << "file in path('" << file_path << "') is not valid TTF."; + return nullptr; + } + return Emboss::create_font_file(file_path.c_str()); +#elif defined(__linux__) + std::string font_path = Slic3r::GUI::get_font_path(font); + if (font_path.empty()){ + BOOST_LOG_TRIVIAL(error) << "Can not read font('" << get_human_readable_name(font) << "'), " + << "file path is empty."; + return nullptr; + } + 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 + return nullptr; +#endif +} + +EmbossStyle::Type WxFontUtils::get_current_type() +{ +#ifdef _WIN32 + return EmbossStyle::Type::wx_win_font_descr; +#elif defined(__APPLE__) + return EmbossStyle::Type::wx_mac_font_descr; +#elif defined(__linux__) + return EmbossStyle::Type::wx_lin_font_descr; +#else + return EmbossStyle::Type::undefined; +#endif +} + +EmbossStyle WxFontUtils::create_emboss_style(const wxFont &font, const std::string& name) +{ + std::string name_item = name.empty()? get_human_readable_name(font) : name; + std::string fontDesc = store_wxFont(font); + EmbossStyle::Type type = get_current_type(); + + // synchronize font property with actual font + FontProp font_prop; + + // The point size is defined as 1/72 of the Anglo-Saxon inch (25.4 mm): it + // is approximately 0.0139 inch or 352.8 um. But it is too small, so I + // decide use point size as mm for emboss + font_prop.size_in_mm = font.GetPointSize(); // *0.3528f; + + WxFontUtils::update_property(font_prop, font); + return { name_item, fontDesc, type, font_prop }; +} + +// NOT working on linux GTK2 +// load font used by Operating system as default GUI +//EmbossStyle WxFontUtils::get_os_font() +//{ +// wxSystemFont system_font = wxSYS_DEFAULT_GUI_FONT; +// wxFont font = wxSystemSettings::GetFont(system_font); +// EmbossStyle es = create_emboss_style(font); +// es.name += std::string(" (OS default)"); +// return es; +//} + +std::string WxFontUtils::get_human_readable_name(const wxFont &font) +{ + if (!font.IsOk()) return "Font is NOT ok."; + // Face name is optional in wxFont + if (!font.GetFaceName().empty()) { + return std::string(font.GetFaceName().c_str()); + } else { + return std::string((font.GetFamilyString() + " " + + font.GetStyleString() + " " + + font.GetWeightString()) + .c_str()); + } +} + +std::string WxFontUtils::store_wxFont(const wxFont &font) +{ + // wxString os = wxPlatformInfo::Get().GetOperatingSystemIdName(); + wxString font_descriptor = font.GetNativeFontInfoDesc(); + BOOST_LOG_TRIVIAL(trace) << "'" << font_descriptor << "' wx string get from GetNativeFontInfoDesc. wxFont " << + "IsOk(" << font.IsOk() << "), " << + "isNull(" << font.IsNull() << ")" << + // "IsFree(" << font.IsFree() << "), " << // on MacOs is no function is free + "IsFixedWidth(" << font.IsFixedWidth() << "), " << + "IsUsingSizeInPixels(" << font.IsUsingSizeInPixels() << "), " << + "Encoding(" << (int)font.GetEncoding() << "), " ; + return std::string(font_descriptor.ToUTF8().data()); +} + +wxFont WxFontUtils::load_wxFont(const std::string &font_descriptor) +{ + BOOST_LOG_TRIVIAL(trace) << "'" << font_descriptor << "'font descriptor string param of load_wxFont()"; + wxString font_descriptor_wx = wxString::FromUTF8(font_descriptor); + BOOST_LOG_TRIVIAL(trace) << "'" << font_descriptor_wx.c_str() << "' wx string descriptor"; + wxFont wx_font(font_descriptor_wx); + BOOST_LOG_TRIVIAL(trace) << "loaded font is '" << get_human_readable_name(wx_font) << "'."; + return wx_font; +} + +using TypeToFamily = boost::bimap; +const TypeToFamily WxFontUtils::type_to_family = + boost::assign::list_of + (wxFONTFAMILY_DEFAULT, "default") + (wxFONTFAMILY_DECORATIVE, "decorative") + (wxFONTFAMILY_ROMAN, "roman") + (wxFONTFAMILY_SCRIPT, "script") + (wxFONTFAMILY_SWISS, "swiss") + (wxFONTFAMILY_MODERN, "modern") + (wxFONTFAMILY_TELETYPE, "teletype"); + +using TypeToStyle = boost::bimap; +const TypeToStyle WxFontUtils::type_to_style = + boost::assign::list_of + (wxFONTSTYLE_ITALIC, "italic") + (wxFONTSTYLE_SLANT, "slant") + (wxFONTSTYLE_NORMAL, "normal"); + +using TypeToWeight = boost::bimap; +const TypeToWeight WxFontUtils::type_to_weight = + boost::assign::list_of + (wxFONTWEIGHT_THIN, "thin") + (wxFONTWEIGHT_EXTRALIGHT, "extraLight") + (wxFONTWEIGHT_LIGHT, "light") + (wxFONTWEIGHT_NORMAL, "normal") + (wxFONTWEIGHT_MEDIUM, "medium") + (wxFONTWEIGHT_SEMIBOLD, "semibold") + (wxFONTWEIGHT_BOLD, "bold") + (wxFONTWEIGHT_EXTRABOLD, "extraBold") + (wxFONTWEIGHT_HEAVY, "heavy") + (wxFONTWEIGHT_EXTRAHEAVY, "extraHeavy"); + +wxFont WxFontUtils::create_wxFont(const EmbossStyle &style) +{ + const FontProp &fp = style.prop; + double point_size = static_cast(fp.size_in_mm); + wxFontInfo info(point_size); + if (fp.family.has_value()) { + auto it = type_to_family.right.find(*fp.family); + if (it != type_to_family.right.end()) info.Family(it->second); + } + // Face names are not portable, so prefer to use Family() in portable code. + /* if (fp.face_name.has_value()) { + wxString face_name(*fp.face_name); + info.FaceName(face_name); + }*/ + if (fp.style.has_value()) { + auto it = type_to_style.right.find(*fp.style); + if (it != type_to_style.right.end()) info.Style(it->second); + } + if (fp.weight.has_value()) { + auto it = type_to_weight.right.find(*fp.weight); + if (it != type_to_weight.right.end()) info.Weight(it->second); + } + + // Improve: load descriptor instead of store to font property to 3mf + // switch (es.type) { + // case EmbossStyle::Type::wx_lin_font_descr: + // case EmbossStyle::Type::wx_win_font_descr: + // case EmbossStyle::Type::wx_mac_font_descr: + // case EmbossStyle::Type::file_path: + // case EmbossStyle::Type::undefined: + // default: + //} + + wxFont wx_font(info); + // Check if exist font file + std::unique_ptr ff = create_font_file(wx_font); + if (ff == nullptr) return {}; + + return wx_font; +} + +void WxFontUtils::update_property(FontProp &font_prop, const wxFont &font) +{ + wxString wx_face_name = font.GetFaceName(); + std::string face_name((const char *) wx_face_name.ToUTF8()); + if (!face_name.empty()) font_prop.face_name = face_name; + + wxFontFamily wx_family = font.GetFamily(); + if (wx_family != wxFONTFAMILY_DEFAULT) { + auto it = type_to_family.left.find(wx_family); + if (it != type_to_family.left.end()) font_prop.family = it->second; + } + + wxFontStyle wx_style = font.GetStyle(); + if (wx_style != wxFONTSTYLE_NORMAL) { + auto it = type_to_style.left.find(wx_style); + if (it != type_to_style.left.end()) font_prop.style = it->second; + } + + wxFontWeight wx_weight = font.GetWeight(); + if (wx_weight != wxFONTWEIGHT_NORMAL) { + auto it = type_to_weight.left.find(wx_weight); + if (it != type_to_weight.left.end()) font_prop.weight = it->second; + } +} + +bool WxFontUtils::is_italic(const wxFont &font) { + wxFontStyle wx_style = font.GetStyle(); + return wx_style == wxFONTSTYLE_ITALIC || + wx_style == wxFONTSTYLE_SLANT; +} + +bool WxFontUtils::is_bold(const wxFont &font) { + wxFontWeight wx_weight = font.GetWeight(); + return wx_weight != wxFONTWEIGHT_NORMAL; +} + +void Slic3r::GUI::WxFontUtils::get_suitable_font_size(int max_height, wxDC &dc) +{ + wxFont font = dc.GetFont(); + if (!font.IsOk()) return; + + int font_size = font.GetPointSize(); + int height = dc.GetFontMetrics().height; + if (height < max_height) /*go smaller*/ + { + while (height < max_height) { + font_size++; + font.SetPointSize(font_size); + dc.SetFont(font); + height = dc.GetFontMetrics().height; + } + + if (height > max_height) + { + font_size--; + font.SetPointSize(font_size); + dc.SetFont(font); + } + } + else if (height > max_height) /*go bigger*/ + { + while (height > max_height && font_size > 1) { + font_size--; + font.SetPointSize(font_size); + dc.SetFont(font); + height = dc.GetFontMetrics().height; + } + } +} + +std::unique_ptr WxFontUtils::set_italic(wxFont &font, const Emboss::FontFile &font_file) +{ + static std::vector italic_styles = { + wxFontStyle::wxFONTSTYLE_ITALIC, + wxFontStyle::wxFONTSTYLE_SLANT + }; + wxFontStyle orig_style = font.GetStyle(); + for (wxFontStyle style : italic_styles) { + font.SetStyle(style); + std::unique_ptr new_font_file = + WxFontUtils::create_font_file(font); + + // can create italic font? + if (new_font_file == nullptr) + continue; + + // is still same font file pointer? + if (font_file == *new_font_file) + continue; + + return new_font_file; + } + // There is NO italic font by wx + font.SetStyle(orig_style); + return nullptr; +} + +std::unique_ptr WxFontUtils::set_bold(wxFont &font, const Emboss::FontFile& font_file) +{ + static std::vector bold_weight = { + wxFontWeight::wxFONTWEIGHT_BOLD, + wxFontWeight::wxFONTWEIGHT_HEAVY, + wxFontWeight::wxFONTWEIGHT_EXTRABOLD, + wxFontWeight::wxFONTWEIGHT_EXTRAHEAVY + }; + wxFontWeight orig_weight = font.GetWeight(); + for (wxFontWeight weight : bold_weight) { + font.SetWeight(weight); + std::unique_ptr new_font_file = + WxFontUtils::create_font_file(font); + + // can create bold font file? + if (new_font_file == nullptr) continue; + + // is still same font file pointer? + if (font_file == *new_font_file) continue; + + return new_font_file; + } + // There is NO bold font by wx + font.SetWeight(orig_weight); + return nullptr; +} diff --git a/src/slic3r/Utils/WxFontUtils.hpp b/src/slic3r/Utils/WxFontUtils.hpp new file mode 100644 index 000000000..fd0a81a88 --- /dev/null +++ b/src/slic3r/Utils/WxFontUtils.hpp @@ -0,0 +1,74 @@ +#ifndef slic3r_WxFontUtils_hpp_ +#define slic3r_WxFontUtils_hpp_ + +#include +#include +#include +#include +#include +#include "libslic3r/Emboss.hpp" + +namespace Slic3r { +namespace GUI { + + // Help class to work with wx widget font object( wxFont ) +class WxFontUtils +{ +public: + // only static functions + WxFontUtils() = delete; + + // check if exist file for wxFont + // return pointer on data or nullptr when can't load + static bool can_load(const wxFont &font); + // os specific load of wxFont + static std::unique_ptr<::Slic3r::Emboss::FontFile> create_font_file(const wxFont &font); + + static EmbossStyle::Type get_current_type(); + static EmbossStyle create_emboss_style(const wxFont &font, const std::string &name = ""); + + static std::string get_human_readable_name(const wxFont &font); + + // serialize / deserialize font + static std::string store_wxFont(const wxFont &font); + static wxFont load_wxFont(const std::string &font_descriptor); + + // Try to create similar font, loaded from 3mf from different Computer + static wxFont create_wxFont(const EmbossStyle &style); + // update font property by wxFont - without emboss depth and font size + static void update_property(FontProp &font_prop, const wxFont &font); + + static bool is_italic(const wxFont &font); + static bool is_bold(const wxFont &font); + + static void get_suitable_font_size(int max_height, wxDC &dc); + + /// + /// Set italic into wx font + /// When italic font is same as original return nullptr. + /// To not load font file twice on success is font_file returned. + /// + /// wx descriptor of font + /// file described in wx font + /// New created font fileon success otherwise nullptr + static std::unique_ptr<::Slic3r::Emboss::FontFile> set_italic(wxFont &font, const ::Slic3r::Emboss::FontFile &prev_font_file); + + /// + /// Set boldness into wx font + /// When bolded font is same as original return nullptr. + /// To not load font file twice on success is font_file returned. + /// + /// wx descriptor of font + /// file described in wx font + /// New created font fileon success otherwise nullptr + static std::unique_ptr<::Slic3r::Emboss::FontFile> set_bold(wxFont &font, const ::Slic3r::Emboss::FontFile &font_file); + + // convert wxFont types to string and vice versa + static const boost::bimap type_to_family; + static const boost::bimap type_to_style; + static const boost::bimap type_to_weight; +}; + +} +} // namespace Slic3r::GUI +#endif // slic3r_WxFontUtils_hpp_