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;
|
Private() = delete;
|
||||||
|
|
||||||
static std::optional<stbtt_fontinfo> load_font_info(const Emboss::Font &font);
|
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(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,
|
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);
|
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)
|
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) {
|
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 {};
|
return {};
|
||||||
}
|
}
|
||||||
stbtt_fontinfo font_info;
|
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;
|
std::cerr << "Can't initialize font." << std::endl;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -424,52 +431,47 @@ std::optional<std::wstring> Emboss::get_font_path(const std::wstring &font_face_
|
|||||||
}
|
}
|
||||||
#endif
|
#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;
|
unsigned int collection_size = 0;
|
||||||
res.buffer = std::move(data);
|
int font_offset = 0;
|
||||||
|
|
||||||
unsigned int index = 0;
|
|
||||||
int font_offset = 0;
|
|
||||||
while (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
|
// 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;
|
std::cerr << "There is no font collection inside data." << std::endl;
|
||||||
return {};
|
return nullptr;
|
||||||
}
|
}
|
||||||
// select default font on index 0
|
auto font_info = Private::load_font_info(data.data());
|
||||||
res.index = 0;
|
if (!font_info.has_value()) return nullptr;
|
||||||
res.count = index;
|
|
||||||
|
|
||||||
auto font_info = Private::load_font_info(res);
|
|
||||||
if (!font_info.has_value()) return {};
|
|
||||||
const stbtt_fontinfo *info = &(*font_info);
|
const stbtt_fontinfo *info = &(*font_info);
|
||||||
// load information about line gap
|
// load information about line gap
|
||||||
stbtt_GetFontVMetrics(info, &res.ascent, &res.descent, &res.linegap);
|
int ascent, descent, linegap;
|
||||||
|
stbtt_GetFontVMetrics(info, &ascent, &descent, &linegap);
|
||||||
return res;
|
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");
|
FILE *file = fopen(file_path, "rb");
|
||||||
if (file == nullptr) {
|
if (file == nullptr) {
|
||||||
std::cerr << "Couldn't open " << file_path << " for reading." << std::endl;
|
std::cerr << "Couldn't open " << file_path << " for reading." << std::endl;
|
||||||
return {};
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// find size of file
|
// find size of file
|
||||||
if (fseek(file, 0L, SEEK_END) != 0) {
|
if (fseek(file, 0L, SEEK_END) != 0) {
|
||||||
std::cerr << "Couldn't fseek file " << file_path << " for size measure." << std::endl;
|
std::cerr << "Couldn't fseek file " << file_path << " for size measure." << std::endl;
|
||||||
return {};
|
return nullptr;
|
||||||
}
|
}
|
||||||
size_t size = ftell(file);
|
size_t size = ftell(file);
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
std::cerr << "Size of font file is zero. Can't read." << std::endl;
|
std::cerr << "Size of font file is zero. Can't read." << std::endl;
|
||||||
return {};
|
return nullptr;
|
||||||
}
|
}
|
||||||
rewind(file);
|
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);
|
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 {};
|
return nullptr;
|
||||||
}
|
}
|
||||||
return load_font(std::move(buffer));
|
return load_font(std::move(buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#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);
|
HDC hdc = ::CreateCompatibleDC(NULL);
|
||||||
if (hdc == NULL) {
|
if (hdc == NULL) {
|
||||||
std::cerr << "Can't create HDC by CreateCompatibleDC(NULL)." << std::endl;
|
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
|
// 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) {
|
if (size == 0 || size == GDI_ERROR) {
|
||||||
std::cerr << "HFONT doesn't have size." << std::endl;
|
std::cerr << "HFONT doesn't have size." << std::endl;
|
||||||
::DeleteDC(hdc);
|
::DeleteDC(hdc);
|
||||||
return {};
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<unsigned char> buffer(size);
|
std::vector<unsigned char> buffer(size);
|
||||||
@ -516,7 +518,7 @@ std::optional<Emboss::Font> Emboss::load_font(HFONT hfont)
|
|||||||
::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 {};
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return load_font(std::move(buffer));
|
return load_font(std::move(buffer));
|
||||||
|
@ -57,15 +57,28 @@ public:
|
|||||||
struct Font
|
struct Font
|
||||||
{
|
{
|
||||||
// loaded data from font file
|
// 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 index; // index of actual file info in collection
|
||||||
unsigned int count = 0; // count of fonts in file collection
|
const unsigned int count; // count of fonts in file collection
|
||||||
|
|
||||||
// vertical position is "scale*(ascent - descent + lineGap)"
|
// 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
|
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>
|
/// <summary>
|
||||||
@ -73,13 +86,13 @@ 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::optional<Font> load_font(const char *file_path);
|
static std::unique_ptr<Font> load_font(const char *file_path);
|
||||||
// data = raw file data
|
// 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
|
#ifdef _WIN32
|
||||||
// fix for unknown pointer HFONT
|
// fix for unknown pointer HFONT
|
||||||
using HFONT = void*;
|
using HFONT = void*;
|
||||||
static std::optional<Font> load_font(HFONT hfont);
|
static std::unique_ptr<Font> load_font(HFONT hfont);
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -839,11 +839,9 @@ bool GLGizmoEmboss::load_font()
|
|||||||
// fill font name after load from .3mf
|
// fill font name after load from .3mf
|
||||||
if (fi.name.empty())
|
if (fi.name.empty())
|
||||||
fi.name = Slic3r::GUI::GLGizmoEmboss::get_file_name(fi.path);
|
fi.name = Slic3r::GUI::GLGizmoEmboss::get_file_name(fi.path);
|
||||||
std::optional<Emboss::Font> font_opt = Emboss::load_font(
|
std::unique_ptr<Emboss::Font> font_ptr = Emboss::load_font(fi.path.c_str());
|
||||||
fi.path.c_str());
|
if (font_ptr == nullptr) return false;
|
||||||
if (!font_opt.has_value()) return false;
|
m_font = std::move(font_ptr);
|
||||||
// TODO: fix copy of font data
|
|
||||||
m_font = std::make_shared<Emboss::Font>(std::move(*font_opt));
|
|
||||||
load_imgui_font();
|
load_imgui_font();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -859,12 +857,17 @@ bool GLGizmoEmboss::load_font()
|
|||||||
|
|
||||||
bool GLGizmoEmboss::load_font(const wxFont &font)
|
bool GLGizmoEmboss::load_font(const wxFont &font)
|
||||||
{
|
{
|
||||||
auto font_opt = WxFontUtils::load_font(font);
|
auto font_ptr = WxFontUtils::load_font(font);
|
||||||
if (!font_opt.has_value()) return false;
|
if (font_ptr == nullptr) return false;
|
||||||
// TODO: fix copy of font data
|
m_font = std::move(font_ptr);
|
||||||
m_font = std::make_shared<Emboss::Font>(std::move(*font_opt));
|
|
||||||
WxFontUtils::update_property(m_font_prop, font);
|
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;
|
m_font_prop.emboss = m_font_prop.size_in_mm / 2.f;
|
||||||
|
|
||||||
load_imgui_font();
|
load_imgui_font();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -12,36 +12,36 @@
|
|||||||
using namespace Slic3r;
|
using namespace Slic3r;
|
||||||
using namespace Slic3r::GUI;
|
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
|
#ifdef _WIN32
|
||||||
return Emboss::load_font(font.GetHFONT());
|
return Emboss::load_font(font.GetHFONT());
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
// use file path
|
// use file path
|
||||||
const wxNativeFontInfo *info = font.GetNativeFontInfo();
|
const wxNativeFontInfo *info = font.GetNativeFontInfo();
|
||||||
if (info == nullptr) return {};
|
if (info == nullptr) return nullptr;
|
||||||
CTFontDescriptorRef descriptor = info->GetCTFontDescriptor();
|
CTFontDescriptorRef descriptor = info->GetCTFontDescriptor();
|
||||||
CFURLRef typeref = (CFURLRef)
|
CFURLRef typeref = (CFURLRef)
|
||||||
CTFontDescriptorCopyAttribute(descriptor, kCTFontURLAttribute);
|
CTFontDescriptorCopyAttribute(descriptor, kCTFontURLAttribute);
|
||||||
CFStringRef url = CFURLGetString(typeref);
|
CFStringRef url = CFURLGetString(typeref);
|
||||||
if (url == NULL) return {};
|
if (url == NULL) return nullptr;
|
||||||
wxString file_uri;
|
wxString file_uri;
|
||||||
wxCFTypeRef(url).GetValue(file_uri);
|
wxCFTypeRef(url).GetValue(file_uri);
|
||||||
std::string file_path(wxURI::Unescape(file_uri).c_str());
|
std::string file_path(wxURI::Unescape(file_uri).c_str());
|
||||||
size_t start = std::string("file://").size();
|
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);
|
file_path = file_path.substr(start, file_path.size() - start);
|
||||||
return Emboss::load_font(file_path.c_str());
|
return Emboss::load_font(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 {};
|
if (font_path.empty()) return nullptr;
|
||||||
return Emboss::load_font(font_path.c_str());
|
return Emboss::load_font(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
|
||||||
return {};
|
return nullptr;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,4 +205,6 @@ void WxFontUtils::update_property(FontProp &font_prop, const wxFont &font)
|
|||||||
auto it = from_weight.find(wx_weight);
|
auto it = from_weight.find(wx_weight);
|
||||||
if (it != from_weight.end()) font_prop.weight = it->second;
|
if (it != from_weight.end()) font_prop.weight = it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#ifndef slic3r_WxFontUtils_hpp_
|
#ifndef slic3r_WxFontUtils_hpp_
|
||||||
#define slic3r_WxFontUtils_hpp_
|
#define slic3r_WxFontUtils_hpp_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <wx/font.h>
|
#include <wx/font.h>
|
||||||
#include "libslic3r/Emboss.hpp"
|
#include "libslic3r/Emboss.hpp"
|
||||||
@ -15,7 +16,7 @@ public:
|
|||||||
WxFontUtils() = delete;
|
WxFontUtils() = delete;
|
||||||
|
|
||||||
// os specific load of wxFont
|
// 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::Type get_actual_type();
|
||||||
static FontItem get_font_item(const wxFont &font);
|
static FontItem get_font_item(const wxFont &font);
|
||||||
|
@ -101,8 +101,8 @@ TEST_CASE("Emboss text", "[Emboss]")
|
|||||||
char letter = '%';
|
char letter = '%';
|
||||||
float flatness = 2.;
|
float flatness = 2.;
|
||||||
|
|
||||||
std::optional<Emboss::Font> font = Emboss::load_font(font_path.c_str());
|
auto font = Emboss::load_font(font_path.c_str());
|
||||||
REQUIRE(font.has_value());
|
REQUIRE(font != nullptr);
|
||||||
|
|
||||||
std::optional<Emboss::Glyph> glyph = Emboss::letter2glyph(*font, letter, flatness);
|
std::optional<Emboss::Glyph> glyph = Emboss::letter2glyph(*font, letter, flatness);
|
||||||
REQUIRE(glyph.has_value());
|
REQUIRE(glyph.has_value());
|
||||||
@ -185,23 +185,38 @@ TEST_CASE("triangle intersection", "[]")
|
|||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
TEST_CASE("Italic check", "[]")
|
TEST_CASE("Italic check", "[]")
|
||||||
{
|
{
|
||||||
//std::string s1 = "italic";
|
std::queue<std::string> dir_paths;
|
||||||
//std::string s2 = "italic";
|
#ifdef _WIN32
|
||||||
//auto pos = s1.find(s2);
|
dir_paths.push("C:/Windows/Fonts");
|
||||||
//std::cout << ((pos != std::string::npos) ? "good" : "bad");
|
#elif defined(__APPLE__)
|
||||||
|
#elif defined(__linux__)
|
||||||
std::string dir_path = "C:/Windows/Fonts";
|
dir_paths.push("/usr/share/fonts");
|
||||||
for (const auto &entry : fs::directory_iterator(dir_path)) {
|
#endif
|
||||||
if (entry.is_directory()) continue;
|
bool exist_italic = false;
|
||||||
const fs::path& act_path = entry.path();
|
bool exist_non_italic = false;
|
||||||
std::string ext = act_path.extension().u8string();
|
while (!dir_paths.empty()) {
|
||||||
std::transform(ext.begin(), ext.end(), ext.begin(), [](unsigned char c) { return std::tolower(c); });
|
std::string dir_path = dir_paths.front();
|
||||||
if (ext != ".ttf") continue;
|
dir_paths.pop();
|
||||||
std::string path_str = act_path.u8string();
|
for (const auto &entry : fs::directory_iterator(dir_path)) {
|
||||||
auto font_opt = Emboss::load_font(path_str.c_str());
|
const fs::path &act_path = entry.path();
|
||||||
if (!font_opt.has_value()) continue;
|
if (entry.is_directory()) {
|
||||||
|
dir_paths.push(act_path.u8string());
|
||||||
std::cout << ((Emboss::is_italic(*font_opt)) ? "[yes] " : "[no ] ")
|
continue;
|
||||||
<< entry.path() << std::endl;
|
}
|
||||||
|
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);
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user