From 4ec4bafe19df5b932390640616859da7ac07ac6a Mon Sep 17 00:00:00 2001 From: Filip Sykala Date: Thu, 6 Jan 2022 15:41:03 +0100 Subject: [PATCH] Create Emboss::Font as unique ptr not optional Reason: Job need pointer on font until finished --- src/libslic3r/Emboss.cpp | 62 +++++++++++++------------ src/libslic3r/Emboss.hpp | 27 ++++++++--- src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp | 21 +++++---- src/slic3r/Utils/WxFontUtils.cpp | 16 ++++--- src/slic3r/Utils/WxFontUtils.hpp | 3 +- tests/libslic3r/test_emboss.cpp | 55 ++++++++++++++-------- 6 files changed, 110 insertions(+), 74 deletions(-) diff --git a/src/libslic3r/Emboss.cpp b/src/libslic3r/Emboss.cpp index da7353e51..c23b73118 100644 --- a/src/libslic3r/Emboss.cpp +++ b/src/libslic3r/Emboss.cpp @@ -23,6 +23,7 @@ public: Private() = delete; static std::optional load_font_info(const Emboss::Font &font); + static std::optional load_font_info(const unsigned char *data, unsigned int index = 0); static std::optional get_glyph(stbtt_fontinfo &font_info, int unicode_letter, float flatness); static std::optional get_glyph(int unicode, const Emboss::Font &font, const FontProp &font_prop, Emboss::Glyphs &cache, std::optional &font_info_opt); @@ -43,13 +44,19 @@ public: std::optional Private::load_font_info(const Emboss::Font &font) { - int font_offset = stbtt_GetFontOffsetForIndex(font.buffer.data(), font.index); + return load_font_info(font.buffer.data(), font.index); +} + +std::optional Private::load_font_info( + const unsigned char *data, unsigned int index) +{ + int font_offset = stbtt_GetFontOffsetForIndex(data, index); if (font_offset < 0) { - std::cerr << "Font index("< Emboss::get_font_path(const std::wstring &font_face_ } #endif -std::optional Emboss::load_font(std::vector data) +std::unique_ptr Emboss::load_font(const std::vector&& data) { - Font res; - res.buffer = std::move(data); - - unsigned int index = 0; - int font_offset = 0; + unsigned int collection_size = 0; + int font_offset = 0; while (font_offset >= 0) { - font_offset = stbtt_GetFontOffsetForIndex(res.buffer.data(), index++); + font_offset = stbtt_GetFontOffsetForIndex(data.data(), collection_size++); } - --index; // last one is bad + --collection_size; // last one is bad // at least one font must be inside collection - if (index < 1) { + if (collection_size < 1) { std::cerr << "There is no font collection inside data." << std::endl; - return {}; + return nullptr; } - // select default font on index 0 - res.index = 0; - res.count = index; + auto font_info = Private::load_font_info(data.data()); + if (!font_info.has_value()) return nullptr; - auto font_info = Private::load_font_info(res); - if (!font_info.has_value()) return {}; const stbtt_fontinfo *info = &(*font_info); // load information about line gap - stbtt_GetFontVMetrics(info, &res.ascent, &res.descent, &res.linegap); - - return res; + int ascent, descent, linegap; + stbtt_GetFontVMetrics(info, &ascent, &descent, &linegap); + return std::make_unique( + std::move(data), collection_size, ascent, descent, linegap); } -std::optional Emboss::load_font(const char *file_path) +std::unique_ptr Emboss::load_font(const char *file_path) { FILE *file = fopen(file_path, "rb"); if (file == nullptr) { std::cerr << "Couldn't open " << file_path << " for reading." << std::endl; - return {}; + return nullptr; } // find size of file if (fseek(file, 0L, SEEK_END) != 0) { std::cerr << "Couldn't fseek file " << file_path << " for size measure." << std::endl; - return {}; + return nullptr; } size_t size = ftell(file); if (size == 0) { std::cerr << "Size of font file is zero. Can't read." << std::endl; - return {}; + return nullptr; } rewind(file); @@ -477,19 +479,19 @@ std::optional Emboss::load_font(const char *file_path) 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 {}; + return nullptr; } return load_font(std::move(buffer)); } #ifdef _WIN32 -std::optional Emboss::load_font(HFONT hfont) +std::unique_ptr Emboss::load_font(HFONT hfont) { HDC hdc = ::CreateCompatibleDC(NULL); if (hdc == NULL) { std::cerr << "Can't create HDC by CreateCompatibleDC(NULL)." << std::endl; - return {}; + return nullptr; } // To retrieve the data from the beginning of the file for TrueType @@ -508,7 +510,7 @@ std::optional Emboss::load_font(HFONT hfont) if (size == 0 || size == GDI_ERROR) { std::cerr << "HFONT doesn't have size." << std::endl; ::DeleteDC(hdc); - return {}; + return nullptr; } std::vector buffer(size); @@ -516,7 +518,7 @@ std::optional Emboss::load_font(HFONT hfont) ::DeleteDC(hdc); if (size != loaded_size) { std::cerr << "Different loaded(from HFONT) data size." << std::endl; - return {}; + return nullptr; } return load_font(std::move(buffer)); diff --git a/src/libslic3r/Emboss.hpp b/src/libslic3r/Emboss.hpp index 541975d54..f92839734 100644 --- a/src/libslic3r/Emboss.hpp +++ b/src/libslic3r/Emboss.hpp @@ -57,15 +57,28 @@ public: struct Font { // loaded data from font file - std::vector buffer; + const std::vector buffer; - unsigned int index = 0; // index of actual file info in collection - unsigned int count = 0; // count of fonts in file collection + unsigned int index; // index of actual file info in collection + const unsigned int count; // count of fonts in file collection // vertical position is "scale*(ascent - descent + lineGap)" - int ascent = 0, descent = 0, linegap = 0; + const int ascent, descent, linegap; Emboss::Glyphs cache; // cache of glyphs + + Font(const std::vector &&buffer, + unsigned int count, + int ascent, + int descent, + int linegap) + : buffer(std::move(buffer)) + , index(0) // select default font on index 0 + , count(count) + , ascent(ascent) + , descent(descent) + , linegap(linegap) + {} }; /// @@ -73,13 +86,13 @@ public: /// /// Location of .ttf or .ttc font file /// Font object when loaded. - static std::optional load_font(const char *file_path); + static std::unique_ptr load_font(const char *file_path); // data = raw file data - static std::optional load_font(std::vector data); + static std::unique_ptr load_font(const std::vector&& data); #ifdef _WIN32 // fix for unknown pointer HFONT using HFONT = void*; - static std::optional load_font(HFONT hfont); + static std::unique_ptr load_font(HFONT hfont); #endif // _WIN32 /// diff --git a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp index 723d0ab83..bccc7a851 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp @@ -839,11 +839,9 @@ bool GLGizmoEmboss::load_font() // fill font name after load from .3mf if (fi.name.empty()) fi.name = Slic3r::GUI::GLGizmoEmboss::get_file_name(fi.path); - std::optional font_opt = Emboss::load_font( - fi.path.c_str()); - if (!font_opt.has_value()) return false; - // TODO: fix copy of font data - m_font = std::make_shared(std::move(*font_opt)); + std::unique_ptr font_ptr = Emboss::load_font(fi.path.c_str()); + if (font_ptr == nullptr) return false; + m_font = std::move(font_ptr); load_imgui_font(); return true; } @@ -859,12 +857,17 @@ bool GLGizmoEmboss::load_font() bool GLGizmoEmboss::load_font(const wxFont &font) { - auto font_opt = WxFontUtils::load_font(font); - if (!font_opt.has_value()) return false; - // TODO: fix copy of font data - m_font = std::make_shared(std::move(*font_opt)); + auto font_ptr = WxFontUtils::load_font(font); + if (font_ptr == nullptr) return false; + m_font = std::move(font_ptr); WxFontUtils::update_property(m_font_prop, font); + + // TODO: fix dynamic creation of italic + + + // TODO: decide when rewrite emboss depth m_font_prop.emboss = m_font_prop.size_in_mm / 2.f; + load_imgui_font(); return true; } diff --git a/src/slic3r/Utils/WxFontUtils.cpp b/src/slic3r/Utils/WxFontUtils.cpp index c33f3d938..5a8853cf3 100644 --- a/src/slic3r/Utils/WxFontUtils.cpp +++ b/src/slic3r/Utils/WxFontUtils.cpp @@ -12,36 +12,36 @@ using namespace Slic3r; using namespace Slic3r::GUI; -std::optional WxFontUtils::load_font(const wxFont &font) +std::unique_ptr WxFontUtils::load_font(const wxFont &font) { - if (!font.IsOk()) return {}; + if (!font.IsOk()) return nullptr; #ifdef _WIN32 return Emboss::load_font(font.GetHFONT()); #elif defined(__APPLE__) // use file path const wxNativeFontInfo *info = font.GetNativeFontInfo(); - if (info == nullptr) return {}; + if (info == nullptr) return nullptr; CTFontDescriptorRef descriptor = info->GetCTFontDescriptor(); CFURLRef typeref = (CFURLRef) CTFontDescriptorCopyAttribute(descriptor, kCTFontURLAttribute); CFStringRef url = CFURLGetString(typeref); - if (url == NULL) return {}; + if (url == NULL) return nullptr; wxString file_uri; wxCFTypeRef(url).GetValue(file_uri); std::string file_path(wxURI::Unescape(file_uri).c_str()); size_t start = std::string("file://").size(); - if (file_path.empty() || file_path.size() <= start) return {}; + 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()); #elif defined(__linux__) static FontConfigHelp help; std::string font_path = help.get_font_path(font); - if (font_path.empty()) return {}; + if (font_path.empty()) return nullptr; return Emboss::load_font(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 {}; + return nullptr; #endif } @@ -205,4 +205,6 @@ void WxFontUtils::update_property(FontProp &font_prop, const wxFont &font) auto it = from_weight.find(wx_weight); if (it != from_weight.end()) font_prop.weight = it->second; } + + } diff --git a/src/slic3r/Utils/WxFontUtils.hpp b/src/slic3r/Utils/WxFontUtils.hpp index a8b518ed9..7d9a9cf0e 100644 --- a/src/slic3r/Utils/WxFontUtils.hpp +++ b/src/slic3r/Utils/WxFontUtils.hpp @@ -1,6 +1,7 @@ #ifndef slic3r_WxFontUtils_hpp_ #define slic3r_WxFontUtils_hpp_ +#include #include #include #include "libslic3r/Emboss.hpp" @@ -15,7 +16,7 @@ public: WxFontUtils() = delete; // os specific load of wxFont - static std::optional load_font(const wxFont &font); + static std::unique_ptr load_font(const wxFont &font); static FontItem::Type get_actual_type(); static FontItem get_font_item(const wxFont &font); diff --git a/tests/libslic3r/test_emboss.cpp b/tests/libslic3r/test_emboss.cpp index 13cdaf29c..c742cdc54 100644 --- a/tests/libslic3r/test_emboss.cpp +++ b/tests/libslic3r/test_emboss.cpp @@ -101,8 +101,8 @@ TEST_CASE("Emboss text", "[Emboss]") char letter = '%'; float flatness = 2.; - std::optional font = Emboss::load_font(font_path.c_str()); - REQUIRE(font.has_value()); + auto font = Emboss::load_font(font_path.c_str()); + REQUIRE(font != nullptr); std::optional glyph = Emboss::letter2glyph(*font, letter, flatness); REQUIRE(glyph.has_value()); @@ -185,23 +185,38 @@ TEST_CASE("triangle intersection", "[]") namespace fs = std::filesystem; TEST_CASE("Italic check", "[]") { - //std::string s1 = "italic"; - //std::string s2 = "italic"; - //auto pos = s1.find(s2); - //std::cout << ((pos != std::string::npos) ? "good" : "bad"); - - std::string dir_path = "C:/Windows/Fonts"; - for (const auto &entry : fs::directory_iterator(dir_path)) { - if (entry.is_directory()) continue; - const fs::path& act_path = entry.path(); - std::string ext = act_path.extension().u8string(); - std::transform(ext.begin(), ext.end(), ext.begin(), [](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()); - if (!font_opt.has_value()) continue; - - std::cout << ((Emboss::is_italic(*font_opt)) ? "[yes] " : "[no ] ") - << entry.path() << std::endl; + std::queue dir_paths; +#ifdef _WIN32 + dir_paths.push("C:/Windows/Fonts"); +#elif defined(__APPLE__) +#elif defined(__linux__) + dir_paths.push("/usr/share/fonts"); +#endif + bool exist_italic = false; + bool exist_non_italic = false; + while (!dir_paths.empty()) { + std::string dir_path = dir_paths.front(); + dir_paths.pop(); + for (const auto &entry : fs::directory_iterator(dir_path)) { + const fs::path &act_path = entry.path(); + if (entry.is_directory()) { + dir_paths.push(act_path.u8string()); + continue; + } + std::string ext = act_path.extension().u8string(); + std::transform(ext.begin(), ext.end(), ext.begin(), + [](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()); + if (font_opt == nullptr) continue; + if (Emboss::is_italic(*font_opt)) + exist_italic = true; + else + exist_non_italic = true; + //std::cout << ((Emboss::is_italic(*font_opt)) ? "[yes] " : "[no ] ") << entry.path() << std::endl; + } } + CHECK(exist_italic); + CHECK(exist_non_italic); } \ No newline at end of file