无法使用libzip和FreeType直接从ZIP加载TTF文件
Cannot load TTF file directly from a ZIP using libzip and FreeType
我试图直接从ZIP存档中加载TTF文件,使用libzip和FreeType。
特别是,我使用的是FT_Open_Face函数,它可以从自定义读/关闭函数(ft_zip_read
和ft_zip_close
)中读取。但是,尽管文件显然已被完全读取,FT_Open_Face
返回FT_Err_Unknown_File_Format
。直接从磁盘打开相同的文件也可以。
我真的不知道怎么调试这个,有人能帮我吗?
我现在唯一能想到的问题是我的ft_zip_read
函数不支持查找,文档说:
这个函数可能被调用来执行查找或跳过操作"计数"为0。非零返回值则表示错误。
它确实以count 0调用了几次,但我看不到任何方法可以在libzip中执行查找。
unsigned long ft_zip_read(FT_Stream stream, unsigned long offset,
unsigned char* buffer, unsigned long count)
{
zip_file* file = static_cast<zip_file*>(stream->descriptor.pointer);
return zip_fread(file, buffer + offset, count);
}
void ft_zip_close(FT_Stream stream)
{
zip_file* file = static_cast<zip_file*>(stream->descriptor.pointer);
zip_fclose(file);
}
FT_Face load_zipped_face(const std::string& name, unsigned int size,
const std::string& zip_path)
{
FT_Library library;
FT_Error error = FT_Init_FreeType(&library);
if (error)
throw freetype_error_string("Failed to initialise FreeType", error);
int zip_error;
zip* zip = zip_open(zip_path.c_str(), 0, &zip_error);
if (!zip) {
std::ostringstream message_stream;
message_stream << "Error loading ZIP (" << zip_path << "): "
<< zip_error;
throw message_stream.str();
}
std::string face_path = name + ".ttf";
struct zip_stat stat;
if (zip_stat(zip, face_path.c_str(), 0, &stat))
throw std::string("zip_stat failed");
zip_file* file = zip_fopen(zip, face_path.c_str(), 0);
if (file == 0)
throw face_path + ": " + strerror(errno);
FT_StreamDesc descriptor;
descriptor.pointer = file;
FT_StreamRec* stream = new FT_StreamRec;
stream->base = 0;
stream->size = stat.size;
stream->descriptor = descriptor;
stream->read = &ft_zip_read;
stream->close = &ft_zip_close;
FT_Open_Args open_args;
open_args.flags = FT_OPEN_STREAM;
open_args.stream = stream;
FT_Face face;
error = FT_Open_Face(library, &open_args, 0, &face);
zip_close(zip);
if (error == FT_Err_Unknown_File_Format)
throw std::string("Unsupported format");
else if (error)
throw freetype_error_string("Unknown error loading font", error);
error = FT_Set_Pixel_Sizes(face, 0, size);
if (error)
throw freetype_error_string("Unable to set pixel sizes", error);
return face;
}
追寻真相
为了能够在压缩的数据流中查找,您需要解压缩流直到您希望查找的点(存在一些例外,例如具有重置标记和索引的流只需要从前一个标记开始解压缩)。如果经常这样做的话,效率会很低(更不用说你需要自己写代码了)。
现在考虑一下,你不想把整个脸加载到内存中并为字体文件定制IO的唯一原因是它太大而无法保存在内存中;这使得FT的流IO接口必须查找。
你能做什么?
如果文件足够小:将其全部读入内存并使用FT_New_Memory_Face
从内存加载face。
如果文件太大以至于您不想一次将整个字体存储在内存中,请将字体文件提取到临时文件中并从中读取。(使用windows/unix/cstdio临时文件API有一个表现良好的临时文件)
如果以上两种方法都不适合您,那么您可以在libzip之上实现自己的缓存和可搜索的zip流,并将其传递给FT。这可能很麻烦,并且涉及一些工作,所以我个人会使用其他两个方法之一:)
- std::原子加载和存储都需要吗
- 如何加载(或映射)文件部分的最大大小,但适合在Windows上的RAM
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- 为什么加载SDF会导致Mobilizer创建闭环错误
- C++atioglxx.pdb未加载错误glBufferData OpenGL
- 如何使用tinyxml2从XML加载父实体和子实体
- 如何在C++中使用pybind11加载一个pickle python列表
- 系统.将数组移交给c#中动态加载的c++DLL时发生AccessViolationException
- 当我尝试加载内核模块时,如何修复C++中的这个 malloc() 错误?
- 树莓上的 Libtorch 无法加载 pt 文件,但在 ubuntu 上工作
- Python ctypes:不会按预期加载 dll
- 为什么会出现 gettnig 运行时错误:加载类型为"_Bit_type"(stl_bvector.h) 的空指针?
- 我的程序有一个保存配置文件的GUI,如何双击此配置文件以直接加载带有配置数据的GUI?
- 保存/加载大量短数组到二进制文件
- 使用 SDL2 和SDL_image C++加载图像
- 无法使用加载库卸载注入的 dll (C++)
- 从zip、内存等加载动态库
- 从 zip 加载到 SDL,代码在 x64 中工作,但不能在 x86 中工作
- 我如何加载QBytesArray包含一个zip文件到QuaZip
- 无法使用libzip和FreeType直接从ZIP加载TTF文件