Create Emboss::Font as unique ptr not optional
Reason: Job need pointer on font until finished
This commit is contained in:
parent
b1b8eee3c9
commit
4ec4bafe19
@ -23,6 +23,7 @@ public:
|
||||
Private() = delete;
|
||||
|
||||
static std::optional<stbtt_fontinfo> load_font_info(const Emboss::Font &font);
|
||||
static std::optional<stbtt_fontinfo> load_font_info(const unsigned char *data, unsigned int index = 0);
|
||||
static std::optional<Emboss::Glyph> get_glyph(stbtt_fontinfo &font_info, int unicode_letter, float flatness);
|
||||
static std::optional<Emboss::Glyph> get_glyph(int unicode, const Emboss::Font &font, const FontProp &font_prop,
|
||||
Emboss::Glyphs &cache, std::optional<stbtt_fontinfo> &font_info_opt);
|
||||
@ -43,13 +44,19 @@ public:
|
||||
|
||||
std::optional<stbtt_fontinfo> 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<stbtt_fontinfo> 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("<<font.index<<") doesn't exist." << std::endl;
|
||||
std::cerr << "Font index(" << index << ") doesn't exist." << std::endl;
|
||||
return {};
|
||||
}
|
||||
stbtt_fontinfo font_info;
|
||||
if (stbtt_InitFont(&font_info, font.buffer.data(), font_offset) == 0) {
|
||||
if (stbtt_InitFont(&font_info, data, font_offset) == 0) {
|
||||
std::cerr << "Can't initialize font." << std::endl;
|
||||
return {};
|
||||
}
|
||||
@ -424,52 +431,47 @@ std::optional<std::wstring> Emboss::get_font_path(const std::wstring &font_face_
|
||||
}
|
||||
#endif
|
||||
|
||||
std::optional<Emboss::Font> Emboss::load_font(std::vector<unsigned char> data)
|
||||
std::unique_ptr<Emboss::Font> Emboss::load_font(const std::vector<unsigned char>&& data)
|
||||
{
|
||||
Font res;
|
||||
res.buffer = std::move(data);
|
||||
|
||||
unsigned int index = 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<Emboss::Font>(
|
||||
std::move(data), collection_size, ascent, descent, linegap);
|
||||
}
|
||||
|
||||
std::optional<Emboss::Font> Emboss::load_font(const char *file_path)
|
||||
std::unique_ptr<Emboss::Font> 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::Font> 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::Font> Emboss::load_font(HFONT hfont)
|
||||
std::unique_ptr<Emboss::Font> 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::Font> 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<unsigned char> buffer(size);
|
||||
@ -516,7 +518,7 @@ std::optional<Emboss::Font> 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));
|
||||
|
@ -57,15 +57,28 @@ public:
|
||||
struct Font
|
||||
{
|
||||
// loaded data from font file
|
||||
std::vector<unsigned char> buffer;
|
||||
const std::vector<unsigned char> 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<unsigned char> &&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)
|
||||
{}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@ -73,13 +86,13 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="file_path">Location of .ttf or .ttc font file</param>
|
||||
/// <returns>Font object when loaded.</returns>
|
||||
static std::optional<Font> load_font(const char *file_path);
|
||||
static std::unique_ptr<Font> load_font(const char *file_path);
|
||||
// data = raw file data
|
||||
static std::optional<Font> load_font(std::vector<unsigned char> data);
|
||||
static std::unique_ptr<Font> load_font(const std::vector<unsigned char>&& data);
|
||||
#ifdef _WIN32
|
||||
// fix for unknown pointer HFONT
|
||||
using HFONT = void*;
|
||||
static std::optional<Font> load_font(HFONT hfont);
|
||||
static std::unique_ptr<Font> load_font(HFONT hfont);
|
||||
#endif // _WIN32
|
||||
|
||||
/// <summary>
|
||||
|
@ -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<Emboss::Font> 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<Emboss::Font>(std::move(*font_opt));
|
||||
std::unique_ptr<Emboss::Font> 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<Emboss::Font>(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;
|
||||
}
|
||||
|
@ -12,36 +12,36 @@
|
||||
using namespace Slic3r;
|
||||
using namespace Slic3r::GUI;
|
||||
|
||||
std::optional<Emboss::Font> WxFontUtils::load_font(const wxFont &font)
|
||||
std::unique_ptr<Emboss::Font> 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef slic3r_WxFontUtils_hpp_
|
||||
#define slic3r_WxFontUtils_hpp_
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <wx/font.h>
|
||||
#include "libslic3r/Emboss.hpp"
|
||||
@ -15,7 +16,7 @@ public:
|
||||
WxFontUtils() = delete;
|
||||
|
||||
// os specific load of wxFont
|
||||
static std::optional<Slic3r::Emboss::Font> load_font(const wxFont &font);
|
||||
static std::unique_ptr<Slic3r::Emboss::Font> load_font(const wxFont &font);
|
||||
|
||||
static FontItem::Type get_actual_type();
|
||||
static FontItem get_font_item(const wxFont &font);
|
||||
|
@ -101,8 +101,8 @@ TEST_CASE("Emboss text", "[Emboss]")
|
||||
char letter = '%';
|
||||
float flatness = 2.;
|
||||
|
||||
std::optional<Emboss::Font> 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<Emboss::Glyph> 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";
|
||||
std::queue<std::string> 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)) {
|
||||
if (entry.is_directory()) continue;
|
||||
const fs::path& act_path = entry.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); });
|
||||
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;
|
||||
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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user