Load dynamic fonts to memory on all platforms, to avoid locked files.

This commit is contained in:
bruvzg 2020-12-05 13:53:58 +02:00
parent eed484d054
commit 29e5b900d0
No known key found for this signature in database
GPG Key ID: 009E1BFE42239B95
4 changed files with 18 additions and 112 deletions

View File

@ -33,8 +33,6 @@
#include FT_STROKER_H #include FT_STROKER_H
#include FT_ADVANCES_H #include FT_ADVANCES_H
HashMap<String, Vector<uint8_t>> DynamicFontDataAdvanced::font_mem_cache;
DynamicFontDataAdvanced::DataAtSize *DynamicFontDataAdvanced::get_data_for_size(int p_size, int p_outline_size) { DynamicFontDataAdvanced::DataAtSize *DynamicFontDataAdvanced::get_data_for_size(int p_size, int p_outline_size) {
ERR_FAIL_COND_V(!valid, nullptr); ERR_FAIL_COND_V(!valid, nullptr);
ERR_FAIL_COND_V(p_size < 0 || p_size > UINT16_MAX, nullptr); ERR_FAIL_COND_V(p_size < 0 || p_size > UINT16_MAX, nullptr);
@ -55,11 +53,10 @@ DynamicFontDataAdvanced::DataAtSize *DynamicFontDataAdvanced::get_data_for_size(
if (E != nullptr) { if (E != nullptr) {
fds = E->get(); fds = E->get();
} else { } else {
// FT_OPEN_STREAM is extremely slow only on Android. if (font_mem == nullptr && font_path != String()) {
if (OS::get_singleton()->get_name() == "Android" && font_mem == nullptr && font_path != String()) { if (!font_mem_cache.empty()) {
if (font_mem_cache.has(font_path)) { font_mem = font_mem_cache.ptr();
font_mem = font_mem_cache[font_path].ptr(); font_mem_size = font_mem_cache.size();
font_mem_size = font_mem_cache[font_path].size();
} else { } else {
FileAccess *f = FileAccess::open(font_path, FileAccess::READ); FileAccess *f = FileAccess::open(font_path, FileAccess::READ);
if (!f) { if (!f) {
@ -67,11 +64,9 @@ DynamicFontDataAdvanced::DataAtSize *DynamicFontDataAdvanced::get_data_for_size(
} }
size_t len = f->get_len(); size_t len = f->get_len();
font_mem_cache[font_path] = Vector<uint8_t>(); font_mem_cache.resize(len);
Vector<uint8_t> &fontdata = font_mem_cache[font_path]; f->get_buffer(font_mem_cache.ptrw(), len);
fontdata.resize(len); font_mem = font_mem_cache.ptr();
f->get_buffer(fontdata.ptrw(), len);
font_mem = fontdata.ptr();
font_mem_size = len; font_mem_size = len;
f->close(); f->close();
} }
@ -79,27 +74,7 @@ DynamicFontDataAdvanced::DataAtSize *DynamicFontDataAdvanced::get_data_for_size(
int error = 0; int error = 0;
fds = memnew(DataAtSize); fds = memnew(DataAtSize);
if (font_mem == nullptr && font_path != String()) { if (font_mem) {
FileAccess *f = FileAccess::open(font_path, FileAccess::READ);
if (!f) {
memdelete(fds);
ERR_FAIL_V_MSG(nullptr, "Cannot open font file '" + font_path + "'.");
}
memset(&fds->stream, 0, sizeof(FT_StreamRec));
fds->stream.base = nullptr;
fds->stream.size = f->get_len();
fds->stream.pos = 0;
fds->stream.descriptor.pointer = f;
fds->stream.read = _ft_stream_io;
fds->stream.close = _ft_stream_close;
FT_Open_Args fargs;
memset(&fargs, 0, sizeof(FT_Open_Args));
fargs.flags = FT_OPEN_STREAM;
fargs.stream = &fds->stream;
error = FT_Open_Face(library, &fargs, 0, &fds->face);
} else if (font_mem) {
memset(&fds->stream, 0, sizeof(FT_StreamRec)); memset(&fds->stream, 0, sizeof(FT_StreamRec));
fds->stream.base = (unsigned char *)font_mem; fds->stream.base = (unsigned char *)font_mem;
fds->stream.size = font_mem_size; fds->stream.size = font_mem_size;
@ -169,25 +144,6 @@ DynamicFontDataAdvanced::DataAtSize *DynamicFontDataAdvanced::get_data_for_size(
return fds; return fds;
} }
unsigned long DynamicFontDataAdvanced::_ft_stream_io(FT_Stream stream, unsigned long offset, unsigned char *buffer, unsigned long count) {
FileAccess *f = (FileAccess *)stream->descriptor.pointer;
if (f->get_position() != offset) {
f->seek(offset);
}
if (count == 0) {
return 0;
}
return f->get_buffer(buffer, count);
}
void DynamicFontDataAdvanced::_ft_stream_close(FT_Stream stream) {
FileAccess *f = (FileAccess *)stream->descriptor.pointer;
f->close();
memdelete(f);
}
Dictionary DynamicFontDataAdvanced::get_feature_list() const { Dictionary DynamicFontDataAdvanced::get_feature_list() const {
_THREAD_SAFE_METHOD_ _THREAD_SAFE_METHOD_
DataAtSize *fds = const_cast<DynamicFontDataAdvanced *>(this)->get_data_for_size(base_size); DataAtSize *fds = const_cast<DynamicFontDataAdvanced *>(this)->get_data_for_size(base_size);

View File

@ -116,7 +116,7 @@ private:
const uint8_t *font_mem = nullptr; const uint8_t *font_mem = nullptr;
int font_mem_size = 0; int font_mem_size = 0;
String font_path; String font_path;
static HashMap<String, Vector<uint8_t>> font_mem_cache; Vector<uint8_t> font_mem_cache;
float rect_margin = 1.f; float rect_margin = 1.f;
int base_size = 16; int base_size = 16;
@ -128,9 +128,6 @@ private:
Map<CacheID, DataAtSize *> size_cache; Map<CacheID, DataAtSize *> size_cache;
Map<CacheID, DataAtSize *> size_cache_outline; Map<CacheID, DataAtSize *> size_cache_outline;
static unsigned long _ft_stream_io(FT_Stream stream, unsigned long offset, unsigned char *buffer, unsigned long count);
static void _ft_stream_close(FT_Stream stream);
DataAtSize *get_data_for_size(int p_size, int p_outline_size = 0); DataAtSize *get_data_for_size(int p_size, int p_outline_size = 0);
TexturePosition find_texture_pos_for_glyph(DataAtSize *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height); TexturePosition find_texture_pos_for_glyph(DataAtSize *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height);

View File

@ -33,8 +33,6 @@
#include FT_STROKER_H #include FT_STROKER_H
#include FT_ADVANCES_H #include FT_ADVANCES_H
HashMap<String, Vector<uint8_t>> DynamicFontDataFallback::font_mem_cache;
DynamicFontDataFallback::DataAtSize *DynamicFontDataFallback::get_data_for_size(int p_size, int p_outline_size) { DynamicFontDataFallback::DataAtSize *DynamicFontDataFallback::get_data_for_size(int p_size, int p_outline_size) {
ERR_FAIL_COND_V(!valid, nullptr); ERR_FAIL_COND_V(!valid, nullptr);
ERR_FAIL_COND_V(p_size < 0 || p_size > UINT16_MAX, nullptr); ERR_FAIL_COND_V(p_size < 0 || p_size > UINT16_MAX, nullptr);
@ -55,11 +53,10 @@ DynamicFontDataFallback::DataAtSize *DynamicFontDataFallback::get_data_for_size(
if (E != nullptr) { if (E != nullptr) {
fds = E->get(); fds = E->get();
} else { } else {
// FT_OPEN_STREAM is extremely slow only on Android. if (font_mem == nullptr && font_path != String()) {
if (OS::get_singleton()->get_name() == "Android" && font_mem == nullptr && font_path != String()) { if (!font_mem_cache.empty()) {
if (font_mem_cache.has(font_path)) { font_mem = font_mem_cache.ptr();
font_mem = font_mem_cache[font_path].ptr(); font_mem_size = font_mem_cache.size();
font_mem_size = font_mem_cache[font_path].size();
} else { } else {
FileAccess *f = FileAccess::open(font_path, FileAccess::READ); FileAccess *f = FileAccess::open(font_path, FileAccess::READ);
if (!f) { if (!f) {
@ -67,11 +64,9 @@ DynamicFontDataFallback::DataAtSize *DynamicFontDataFallback::get_data_for_size(
} }
size_t len = f->get_len(); size_t len = f->get_len();
font_mem_cache[font_path] = Vector<uint8_t>(); font_mem_cache.resize(len);
Vector<uint8_t> &fontdata = font_mem_cache[font_path]; f->get_buffer(font_mem_cache.ptrw(), len);
fontdata.resize(len); font_mem = font_mem_cache.ptr();
f->get_buffer(fontdata.ptrw(), len);
font_mem = fontdata.ptr();
font_mem_size = len; font_mem_size = len;
f->close(); f->close();
} }
@ -79,27 +74,7 @@ DynamicFontDataFallback::DataAtSize *DynamicFontDataFallback::get_data_for_size(
int error = 0; int error = 0;
fds = memnew(DataAtSize); fds = memnew(DataAtSize);
if (font_mem == nullptr && font_path != String()) { if (font_mem) {
FileAccess *f = FileAccess::open(font_path, FileAccess::READ);
if (!f) {
memdelete(fds);
ERR_FAIL_V_MSG(nullptr, "Cannot open font file '" + font_path + "'.");
}
memset(&fds->stream, 0, sizeof(FT_StreamRec));
fds->stream.base = nullptr;
fds->stream.size = f->get_len();
fds->stream.pos = 0;
fds->stream.descriptor.pointer = f;
fds->stream.read = _ft_stream_io;
fds->stream.close = _ft_stream_close;
FT_Open_Args fargs;
memset(&fargs, 0, sizeof(FT_Open_Args));
fargs.flags = FT_OPEN_STREAM;
fargs.stream = &fds->stream;
error = FT_Open_Face(library, &fargs, 0, &fds->face);
} else if (font_mem) {
memset(&fds->stream, 0, sizeof(FT_StreamRec)); memset(&fds->stream, 0, sizeof(FT_StreamRec));
fds->stream.base = (unsigned char *)font_mem; fds->stream.base = (unsigned char *)font_mem;
fds->stream.size = font_mem_size; fds->stream.size = font_mem_size;
@ -161,25 +136,6 @@ DynamicFontDataFallback::DataAtSize *DynamicFontDataFallback::get_data_for_size(
return fds; return fds;
} }
unsigned long DynamicFontDataFallback::_ft_stream_io(FT_Stream stream, unsigned long offset, unsigned char *buffer, unsigned long count) {
FileAccess *f = (FileAccess *)stream->descriptor.pointer;
if (f->get_position() != offset) {
f->seek(offset);
}
if (count == 0) {
return 0;
}
return f->get_buffer(buffer, count);
}
void DynamicFontDataFallback::_ft_stream_close(FT_Stream stream) {
FileAccess *f = (FileAccess *)stream->descriptor.pointer;
f->close();
memdelete(f);
}
DynamicFontDataFallback::TexturePosition DynamicFontDataFallback::find_texture_pos_for_glyph(DynamicFontDataFallback::DataAtSize *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height) { DynamicFontDataFallback::TexturePosition DynamicFontDataFallback::find_texture_pos_for_glyph(DynamicFontDataFallback::DataAtSize *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height) {
TexturePosition ret; TexturePosition ret;
ret.index = -1; ret.index = -1;

View File

@ -107,7 +107,7 @@ private:
const uint8_t *font_mem = nullptr; const uint8_t *font_mem = nullptr;
int font_mem_size = 0; int font_mem_size = 0;
String font_path; String font_path;
static HashMap<String, Vector<uint8_t>> font_mem_cache; Vector<uint8_t> font_mem_cache;
float rect_margin = 1.f; float rect_margin = 1.f;
int base_size = 16; int base_size = 16;
@ -119,9 +119,6 @@ private:
Map<CacheID, DataAtSize *> size_cache; Map<CacheID, DataAtSize *> size_cache;
Map<CacheID, DataAtSize *> size_cache_outline; Map<CacheID, DataAtSize *> size_cache_outline;
static unsigned long _ft_stream_io(FT_Stream stream, unsigned long offset, unsigned char *buffer, unsigned long count);
static void _ft_stream_close(FT_Stream stream);
DataAtSize *get_data_for_size(int p_size, int p_outline_size = 0); DataAtSize *get_data_for_size(int p_size, int p_outline_size = 0);
TexturePosition find_texture_pos_for_glyph(DataAtSize *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height); TexturePosition find_texture_pos_for_glyph(DataAtSize *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height);